Compare commits
14 Commits
dev
...
fix/linux-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aab275cacd | ||
|
|
b66e3def09 | ||
|
|
39a652df5b | ||
|
|
542ae60d27 | ||
|
|
87d90ee92f | ||
|
|
d906df6927 | ||
|
|
9a472c6793 | ||
|
|
9bf974a2f4 | ||
|
|
46100fd311 | ||
|
|
34b62f8fd6 | ||
|
|
b8e9ec8570 | ||
|
|
c35988d79f | ||
|
|
410538c6b2 | ||
|
|
cc71330c27 |
82
.github/workflows/deploy.yml
vendored
@@ -745,37 +745,11 @@ jobs:
|
||||
needs: Bake-Prebuilts-Android
|
||||
if: ${{ always() }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- label: 'android9-10'
|
||||
qt_version: '6.10.1'
|
||||
min_sdk: 28
|
||||
max_sdk: 29
|
||||
version_code_offset: 0
|
||||
build_aab: true
|
||||
- label: 'android11+'
|
||||
qt_version: '6.10.3'
|
||||
min_sdk: 30
|
||||
max_sdk: ''
|
||||
version_code_offset: 1
|
||||
build_aab: true
|
||||
- label: 'android9-10-qt610-3'
|
||||
qt_version: '6.10.3'
|
||||
min_sdk: 28
|
||||
max_sdk: 29
|
||||
version_code_offset: 0
|
||||
build_aab: false
|
||||
|
||||
env:
|
||||
ANDROID_PLATFORM: android-${{ matrix.min_sdk }}
|
||||
ANDROID_PLATFORM: android-28
|
||||
NDK_VERSION: 27.0.11718014
|
||||
QT_VERSION: ${{ matrix.qt_version }}
|
||||
QT_VERSION: 6.10.3
|
||||
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
|
||||
APP_ANDROID_MIN_SDK: ${{ matrix.min_sdk }}
|
||||
APP_ANDROID_MAX_SDK: ${{ matrix.max_sdk }}
|
||||
APP_ANDROID_VERSION_CODE_OFFSET: ${{ matrix.version_code_offset }}
|
||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||
PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }}
|
||||
FALLBACK_S3_ENDPOINT: ${{ secrets.FALLBACK_S3_ENDPOINT }}
|
||||
@@ -883,82 +857,62 @@ jobs:
|
||||
QT_ANDROID_KEYSTORE_PATH: ${{ github.workspace }}/android.keystore
|
||||
QT_ANDROID_KEYSTORE_ALIAS: ${{ secrets.ANDROID_RELEASE_KEYSTORE_KEY_ALIAS }}
|
||||
QT_ANDROID_KEYSTORE_STORE_PASS: ${{ secrets.ANDROID_RELEASE_KEYSTORE_KEY_PASS }}
|
||||
LABEL: ${{ matrix.label }}
|
||||
BUILD_AAB: ${{ matrix.build_aab }}
|
||||
shell: bash
|
||||
run: |
|
||||
OUT=deploy/artifacts
|
||||
rm -rf $OUT && mkdir -p $OUT
|
||||
|
||||
if [[ "$BUILD_AAB" == "true" ]]; then
|
||||
deploy/build.sh -t android --sign --aab
|
||||
else
|
||||
deploy/build.sh -t android --sign
|
||||
fi
|
||||
deploy/build.sh -t android --sign --aab
|
||||
|
||||
VERSION=$(grep CMAKE_PROJECT_VERSION:STATIC deploy/build/CMakeCache.txt | cut -d= -f2)
|
||||
|
||||
mv deploy/build/client/android-build/AmneziaVPN.apk \
|
||||
$OUT/AmneziaVPN_${VERSION}_${LABEL}_universal.apk
|
||||
|
||||
if [[ "$BUILD_AAB" == "true" ]]; then
|
||||
mv deploy/build/client/android-build/build/outputs/bundle/release/android-build-release.aab \
|
||||
$OUT/AmneziaVPN_${VERSION}_${LABEL}.aab
|
||||
fi
|
||||
(cd deploy/build/client/android-build && mv AmneziaVPN.apk AmneziaVPN_${VERSION}_android9+_universal.apk)
|
||||
(cd deploy/build/client/android-build/build/outputs/bundle/release && mv android-build-release.aab AmneziaVPN_${VERSION}.aab)
|
||||
|
||||
for abi in arm64-v8a armeabi-v7a x86 x86_64; do
|
||||
deploy/build.sh -t android --sign --abi ${abi} --build ./deploy/build/${abi}
|
||||
mv deploy/build/${abi}/client/android-build/AmneziaVPN.apk \
|
||||
$OUT/AmneziaVPN_${VERSION}_${LABEL}_${abi}.apk
|
||||
(cd deploy/build/${abi}/client/android-build && mv AmneziaVPN.apk AmneziaVPN_${VERSION}_android9+_${abi}.apk)
|
||||
done
|
||||
|
||||
ls -l $OUT
|
||||
|
||||
- name: 'Upload universal APK'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: deploy/artifacts/*_universal.apk
|
||||
path: deploy/build/client/android-build/*.apk
|
||||
archive: false
|
||||
retention-days: 7
|
||||
|
||||
- name: 'Upload AAB'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: deploy/build/client/android-build/build/outputs/bundle/release/*.aab
|
||||
archive: false
|
||||
retention-days: 7
|
||||
|
||||
- name: 'Upload arm64-v8a APK'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: deploy/artifacts/*_arm64-v8a.apk
|
||||
path: deploy/build/arm64-v8a/client/android-build/*.apk
|
||||
archive: false
|
||||
retention-days: 7
|
||||
|
||||
- name: 'Upload armeabi-v7a APK'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: deploy/artifacts/*_armeabi-v7a.apk
|
||||
path: deploy/build/armeabi-v7a/client/android-build/*.apk
|
||||
archive: false
|
||||
retention-days: 7
|
||||
|
||||
- name: 'Upload x86 APK'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: deploy/artifacts/*_x86.apk
|
||||
path: deploy/build/x86/client/android-build/*.apk
|
||||
archive: false
|
||||
retention-days: 7
|
||||
|
||||
- name: 'Upload x86_64 APK'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: deploy/artifacts/*_x86_64.apk
|
||||
path: deploy/build/x86_64/client/android-build/*.apk
|
||||
archive: false
|
||||
retention-days: 7
|
||||
|
||||
- name: 'Upload AAB'
|
||||
if: ${{ matrix.build_aab }}
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
path: deploy/artifacts/*.aab
|
||||
archive: false
|
||||
retention-days: 7
|
||||
|
||||
# ------------------------------------------------------
|
||||
|
||||
Extra:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@@ -4,9 +4,7 @@ set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(PROJECT AmneziaVPN)
|
||||
if(NOT AMNEZIAVPN_VERSION)
|
||||
set(AMNEZIAVPN_VERSION 5.0.1.5 CACHE STRING "Client app version")
|
||||
endif()
|
||||
set(AMNEZIAVPN_VERSION 5.0.1.0)
|
||||
|
||||
set(QT_CREATOR_SKIP_PACKAGE_MANAGER_SETUP ON CACHE BOOL "" FORCE)
|
||||
set(CMAKE_PROJECT_TOP_LEVEL_INCLUDES
|
||||
@@ -30,12 +28,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
|
||||
set(RELEASE_DATE "${CURRENT_DATE}")
|
||||
|
||||
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
|
||||
|
||||
# bump by 2 on every release, because we're releasing two versions on the play store
|
||||
set(APP_ANDROID_VERSION_CODE 2152)
|
||||
if(DEFINED APP_ANDROID_VERSION_CODE_OFFSET)
|
||||
math(EXPR APP_ANDROID_VERSION_CODE "${APP_ANDROID_VERSION_CODE} + ${APP_ANDROID_VERSION_CODE_OFFSET}")
|
||||
endif()
|
||||
set(APP_ANDROID_VERSION_CODE 2141)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
set(MZ_PLATFORM_NAME "linux")
|
||||
@@ -61,14 +54,14 @@ if(APPLE AND NOT IOS)
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deploy/data/pf-templates/amn.400.allowPIA.conf.in"
|
||||
"${CMAKE_SOURCE_DIR}/deploy/data/pf-templates/amn.400.allowPIA.conf.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/amn.400.allowPIA.conf"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
file(COPY_FILE
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/amn.400.allowPIA.conf"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deploy/data/macos/pf/amn.400.allowPIA.conf"
|
||||
"${CMAKE_SOURCE_DIR}/deploy/data/macos/pf/amn.400.allowPIA.conf"
|
||||
ONLY_IF_DIFFERENT
|
||||
)
|
||||
endif()
|
||||
|
||||
2
client/3rd/amneziawg-apple
vendored
@@ -1,8 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cmake/clientBrandingDefaults.cmake)
|
||||
|
||||
set(PROJECT ${CLIENT_TARGET_NAME})
|
||||
set(PROJECT AmneziaVPN)
|
||||
project(${PROJECT})
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
@@ -59,9 +57,6 @@ qt_add_executable(${PROJECT} MANUAL_FINALIZATION)
|
||||
target_include_directories(${PROJECT} PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
|
||||
)
|
||||
target_compile_definitions(${PROJECT} PRIVATE
|
||||
CLIENT_KEYCHAIN_NAME_STR=\"${CLIENT_KEYCHAIN_NAME}\"
|
||||
)
|
||||
|
||||
if(WIN32 OR (APPLE AND NOT IOS AND NOT MACOS_NE) OR (LINUX AND NOT ANDROID))
|
||||
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_interface.rep)
|
||||
@@ -72,34 +67,24 @@ qt6_add_resources(QRC ${QRC}
|
||||
${CMAKE_CURRENT_LIST_DIR}/images/images.qrc
|
||||
${CMAKE_CURRENT_LIST_DIR}/images/flagKit.qrc
|
||||
${CMAKE_CURRENT_LIST_DIR}/client_scripts/clientScripts.qrc
|
||||
${CLIENT_QML_QRC_FILE}
|
||||
${CMAKE_CURRENT_LIST_DIR}/ui/qml/qml.qrc
|
||||
${CMAKE_CURRENT_LIST_DIR}/server_scripts/serverScripts.qrc
|
||||
${CLIENT_EXTRA_QRC}
|
||||
)
|
||||
|
||||
# -- i18n begin
|
||||
if(CLIENT_TS_FILES)
|
||||
set(AMNEZIAVPN_TS_FILES ${CLIENT_TS_FILES})
|
||||
else()
|
||||
set(AMNEZIAVPN_TS_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/${CLIENT_TS_PREFIX}_ru_RU.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/${CLIENT_TS_PREFIX}_zh_CN.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/${CLIENT_TS_PREFIX}_fa_IR.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/${CLIENT_TS_PREFIX}_ar_EG.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/${CLIENT_TS_PREFIX}_my_MM.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/${CLIENT_TS_PREFIX}_uk_UA.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/${CLIENT_TS_PREFIX}_ur_PK.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/${CLIENT_TS_PREFIX}_hi_IN.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/${CLIENT_TS_PREFIX}_es_ES.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/${CLIENT_TS_PREFIX}_ko_KR.ts
|
||||
)
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE AMNEZIAVPN_QML_FILES ${CMAKE_CURRENT_LIST_DIR}/ui/qml/*.qml)
|
||||
set(AMNEZIAVPN_TS_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ru_RU.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_zh_CN.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_fa_IR.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ar_EG.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_my_MM.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_uk_UA.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ur_PK.ts
|
||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_hi_IN.ts
|
||||
)
|
||||
|
||||
qt6_add_translations(${PROJECT}
|
||||
TS_FILES ${AMNEZIAVPN_TS_FILES}
|
||||
SOURCES ${AMNEZIAVPN_QML_FILES}
|
||||
RESOURCE_PREFIX "/translations"
|
||||
)
|
||||
# -- i18n end
|
||||
@@ -116,18 +101,13 @@ endif()
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cmake/3rdparty.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cmake/sources.cmake)
|
||||
|
||||
set(_client_include_dirs
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_LIST_DIR}/../ipc
|
||||
${CMAKE_CURRENT_LIST_DIR}/../common/logger
|
||||
${CMAKE_CURRENT_LIST_DIR}/../common/crypto
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
if(CLIENT_BRANDING_INCLUDE_DIR)
|
||||
list(APPEND _client_include_dirs ${CLIENT_BRANDING_INCLUDE_DIR})
|
||||
endif()
|
||||
list(APPEND _client_include_dirs ${CMAKE_CURRENT_LIST_DIR})
|
||||
include_directories(${_client_include_dirs})
|
||||
|
||||
if(MACOS_NE)
|
||||
message("MACOS_NE is ON")
|
||||
@@ -143,26 +123,6 @@ include_directories(mozilla/shared)
|
||||
include_directories(mozilla/models)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_LIST_DIR}/../version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/core/utils)
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_LIST_DIR}/core/utils/appUiConfig.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/core/utils/appUiConfig.h
|
||||
@ONLY
|
||||
)
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_LIST_DIR}/core/utils/swiftBridgeConfig.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/core/utils/swiftBridgeConfig.h
|
||||
@ONLY
|
||||
)
|
||||
# Swift can't consume a `-DGROUP_ID="value"` compile define (Swift -D flags are
|
||||
# presence-only), unlike the Objective-C++ sources that read GROUP_ID directly.
|
||||
# Generate a Swift constant instead so Log.swift can use the branded app group.
|
||||
set(CLIENT_GROUP_IDENTIFIER_SWIFT_FILE ${CMAKE_CURRENT_BINARY_DIR}/platforms/ios/GroupIdentifier.swift)
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_LIST_DIR}/platforms/ios/GroupIdentifier.swift.in
|
||||
${CLIENT_GROUP_IDENTIFIER_SWIFT_FILE}
|
||||
@ONLY
|
||||
)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
target_compile_definitions(${PROJECT} PRIVATE "MZ_DEBUG")
|
||||
@@ -190,6 +150,18 @@ if(APPLE)
|
||||
cmake_policy(SET CMP0099 NEW)
|
||||
cmake_policy(SET CMP0114 NEW)
|
||||
|
||||
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 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()
|
||||
|
||||
set(CMAKE_XCODE_GENERATE_SCHEME FALSE)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM ${BUILD_VPN_DEVELOPMENT_TEAM})
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "ui/models/installedAppsModel.h"
|
||||
#include "ui/utils/mtProxyPublicHostInput.h"
|
||||
#include "version.h"
|
||||
#include "core/utils/appUiConfig.h"
|
||||
|
||||
#include "platforms/ios/QRCodeReaderBase.h"
|
||||
#ifdef Q_OS_IOS
|
||||
@@ -103,7 +102,7 @@ void AmneziaApplication::init()
|
||||
{
|
||||
m_engine = new QQmlApplicationEngine;
|
||||
|
||||
const QUrl url(QStringLiteral(APP_QML_ENTRYPOINT));
|
||||
const QUrl url(QStringLiteral("qrc:/ui/qml/main2.qml"));
|
||||
QObject::connect(
|
||||
m_engine, &QQmlApplicationEngine::objectCreated, this,
|
||||
[this, url](QObject *obj, const QUrl &objUrl) {
|
||||
@@ -156,7 +155,7 @@ void AmneziaApplication::init()
|
||||
m_marketplaceUpdateController.reset(new MarketplaceUpdateController());
|
||||
m_marketplaceUpdateController->start();
|
||||
|
||||
m_engine->addImportPath(QStringLiteral(APP_QML_IMPORT_PATH));
|
||||
m_engine->addImportPath("qrc:/ui/qml/Modules/");
|
||||
|
||||
if (m_parser.isSet(m_optImport)) {
|
||||
const QString data = m_parser.value(m_optImport);
|
||||
@@ -245,7 +244,7 @@ void AmneziaApplication::loadFonts()
|
||||
{
|
||||
QQuickStyle::setStyle("Basic");
|
||||
|
||||
QFontDatabase::addApplicationFont(QStringLiteral(APP_UI_FONT_RESOURCE));
|
||||
QFontDatabase::addApplicationFont(":/fonts/pt-root-ui_vf.ttf");
|
||||
}
|
||||
|
||||
bool AmneziaApplication::parseCommands()
|
||||
@@ -272,7 +271,7 @@ bool AmneziaApplication::parseCommands()
|
||||
|
||||
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
|
||||
void AmneziaApplication::startLocalServer() {
|
||||
const QString serverName(APP_INSTANCE_NAME);
|
||||
const QString serverName("AmneziaVPNInstance");
|
||||
QLocalServer::removeServer(serverName);
|
||||
|
||||
QLocalServer *server = new QLocalServer(this);
|
||||
|
||||
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 35 KiB |
@@ -148,10 +148,6 @@ open class Wireguard : Protocol() {
|
||||
?.let { setKeepaliveTimeout(it) }
|
||||
configData.optStringOrNull("MaxHandshakeAttempts")?.trim()?.takeIf { it.isNotEmpty() }
|
||||
?.let { setMaxHandshakeAttempts(it) }
|
||||
configData.optStringOrNull("RandomTrailers")?.trim()?.takeIf { it.isNotEmpty() }
|
||||
?.let { setRandomTrailers(it) }
|
||||
configData.optStringOrNull("DisableCookies")?.trim()?.takeIf { it.isNotEmpty() }
|
||||
?.let { setDisableCookies(it) }
|
||||
}
|
||||
|
||||
private fun start(
|
||||
|
||||
@@ -38,8 +38,6 @@ open class WireguardConfig protected constructor(
|
||||
val rejectAfterTime: String?,
|
||||
val keepaliveTimeout: String?,
|
||||
val maxHandshakeAttempts: String?,
|
||||
val randomTrailers: String?,
|
||||
val disableCookies: String?,
|
||||
) : ProtocolConfig(protocolConfigBuilder) {
|
||||
|
||||
protected constructor(builder: Builder) : this(
|
||||
@@ -73,8 +71,6 @@ open class WireguardConfig protected constructor(
|
||||
builder.rejectAfterTime,
|
||||
builder.keepaliveTimeout,
|
||||
builder.maxHandshakeAttempts,
|
||||
builder.randomTrailers,
|
||||
builder.disableCookies,
|
||||
)
|
||||
|
||||
fun toWgUserspaceString(): String = with(StringBuilder()) {
|
||||
@@ -112,8 +108,6 @@ open class WireguardConfig protected constructor(
|
||||
rejectAfterTime?.takeIf { it.isNotEmpty() }?.let { appendLine("reject_after_time=$it") }
|
||||
keepaliveTimeout?.takeIf { it.isNotEmpty() }?.let { appendLine("keepalive_timeout=$it") }
|
||||
maxHandshakeAttempts?.takeIf { it.isNotEmpty() }?.let { appendLine("max_handshake_attempts=$it") }
|
||||
randomTrailers?.takeIf { it.isNotEmpty() }?.let { appendLine("random_trailers=${it.toUapiBool()}") }
|
||||
disableCookies?.takeIf { it.isNotEmpty() }?.let { appendLine("disable_cookies=${it.toUapiBool()}") }
|
||||
}
|
||||
|
||||
private fun validateProtocolExtensionParameters() {
|
||||
@@ -183,8 +177,6 @@ open class WireguardConfig protected constructor(
|
||||
internal var rejectAfterTime: String? = null
|
||||
internal var keepaliveTimeout: String? = null
|
||||
internal var maxHandshakeAttempts: String? = null
|
||||
internal var randomTrailers: String? = null
|
||||
internal var disableCookies: String? = null
|
||||
|
||||
fun setEndpoint(endpoint: InetEndpoint) = apply { this.endpoint = endpoint }
|
||||
|
||||
@@ -221,8 +213,6 @@ open class WireguardConfig protected constructor(
|
||||
fun setRejectAfterTime(rejectAfterTime: String) = apply { this.rejectAfterTime = rejectAfterTime }
|
||||
fun setKeepaliveTimeout(keepaliveTimeout: String) = apply { this.keepaliveTimeout = keepaliveTimeout }
|
||||
fun setMaxHandshakeAttempts(maxHandshakeAttempts: String) = apply { this.maxHandshakeAttempts = maxHandshakeAttempts }
|
||||
fun setRandomTrailers(randomTrailers: String) = apply { this.randomTrailers = randomTrailers }
|
||||
fun setDisableCookies(disableCookies: String) = apply { this.disableCookies = disableCookies }
|
||||
|
||||
override fun build(): WireguardConfig = configBuild().run { WireguardConfig(this@Builder) }
|
||||
}
|
||||
@@ -234,9 +224,3 @@ open class WireguardConfig protected constructor(
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
internal fun String.base64ToHex(): String = Base64.decode(this, Base64.DEFAULT).toHexString()
|
||||
|
||||
/** Converts awg-quick on/off (and 0/1/true/false) to UAPI 1/0 for amneziawg-go ParseBool. */
|
||||
internal fun String.toUapiBool(): String = when (trim().lowercase()) {
|
||||
"on", "1", "true", "t", "yes" -> "1"
|
||||
else -> "0"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
message("Client android ${CMAKE_ANDROID_ARCH_ABI} build")
|
||||
|
||||
if(NOT DEFINED APP_ANDROID_MIN_SDK)
|
||||
set(APP_ANDROID_MIN_SDK 28)
|
||||
endif()
|
||||
set(APP_ANDROID_MIN_SDK 28)
|
||||
set(ANDROID_PLATFORM "android-${APP_ANDROID_MIN_SDK}" CACHE STRING
|
||||
"The minimum API level supported by the application or library" FORCE)
|
||||
|
||||
@@ -15,6 +13,7 @@ set_target_properties(${PROJECT} PROPERTIES
|
||||
QT_ANDROID_MIN_SDK_VERSION ${APP_ANDROID_MIN_SDK}
|
||||
QT_ANDROID_TARGET_SDK_VERSION 36
|
||||
QT_ANDROID_SDK_BUILD_TOOLS_REVISION 36.0.0
|
||||
QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android
|
||||
)
|
||||
|
||||
set(QT_ANDROID_MULTI_ABI_FORWARD_VARS "QT_NO_GLOBAL_APK_TARGET_PART_OF_ALL;CMAKE_BUILD_TYPE")
|
||||
@@ -54,27 +53,3 @@ file(COPY ${AMNEZIA_LIBXRAY_PATH} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/androi
|
||||
find_package(openvpn-pt-android REQUIRED)
|
||||
set(LIBS ${LIBS} amnezia::openvpn-pt-android)
|
||||
set_property(TARGET ${PROJECT} APPEND PROPERTY QT_ANDROID_EXTRA_LIBS ${OPENVPN_PT_ANDROID_LIBCK_OVPN_PLUGIN_PATH})
|
||||
|
||||
set(APP_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android)
|
||||
|
||||
if(APP_ANDROID_MAX_SDK)
|
||||
set(APP_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/android-package-source)
|
||||
file(REMOVE_RECURSE ${APP_ANDROID_PACKAGE_SOURCE_DIR})
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/android/ DESTINATION ${APP_ANDROID_PACKAGE_SOURCE_DIR})
|
||||
|
||||
set(manifest_path ${APP_ANDROID_PACKAGE_SOURCE_DIR}/AndroidManifest.xml)
|
||||
set(manifest_anchor "android:installLocation=\"auto\">")
|
||||
file(READ ${manifest_path} manifest_contents)
|
||||
string(REPLACE
|
||||
"${manifest_anchor}"
|
||||
"${manifest_anchor}\n\n <uses-sdk android:maxSdkVersion=\"${APP_ANDROID_MAX_SDK}\" />"
|
||||
patched_contents "${manifest_contents}")
|
||||
if(patched_contents STREQUAL manifest_contents)
|
||||
message(FATAL_ERROR
|
||||
"Failed to set maxSdkVersion=${APP_ANDROID_MAX_SDK}: anchor '${manifest_anchor}' "
|
||||
"not found in ${CMAKE_CURRENT_SOURCE_DIR}/android/AndroidManifest.xml")
|
||||
endif()
|
||||
file(WRITE ${manifest_path} "${patched_contents}")
|
||||
endif()
|
||||
|
||||
set_property(TARGET ${PROJECT} PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR ${APP_ANDROID_PACKAGE_SOURCE_DIR})
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
if(NOT CLIENT_ANDROID_PACKAGE)
|
||||
set(CLIENT_ANDROID_PACKAGE "org.amnezia.vpn" CACHE STRING "Android package name for Play Store version lookup")
|
||||
endif()
|
||||
@@ -1,22 +0,0 @@
|
||||
if(NOT CLIENT_SWIFT_MODULE_NAME)
|
||||
set(CLIENT_SWIFT_MODULE_NAME "${CLIENT_APPLICATION_NAME}" CACHE STRING "Swift module name for Objective-C interop header")
|
||||
endif()
|
||||
if(NOT CLIENT_SWIFT_OBJC_HEADER_NAME)
|
||||
set(CLIENT_SWIFT_OBJC_HEADER_NAME "${CLIENT_SWIFT_MODULE_NAME}-Swift.h" CACHE STRING "Generated Swift Objective-C header name")
|
||||
endif()
|
||||
if(NOT CLIENT_NETWORK_EXTENSION_NAME)
|
||||
set(CLIENT_NETWORK_EXTENSION_NAME "${CLIENT_APPLICATION_NAME}NetworkExtension" CACHE STRING "Display name for Apple network extension targets")
|
||||
endif()
|
||||
|
||||
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 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()
|
||||
@@ -1,60 +0,0 @@
|
||||
if(NOT CLIENT_TARGET_NAME)
|
||||
set(CLIENT_TARGET_NAME "AmneziaVPN" CACHE STRING "Client executable target name")
|
||||
endif()
|
||||
if(NOT CLIENT_APPLICATION_NAME)
|
||||
set(CLIENT_APPLICATION_NAME "AmneziaVPN" CACHE STRING "Application display and executable name")
|
||||
endif()
|
||||
if(NOT CLIENT_SERVICE_NAME)
|
||||
set(CLIENT_SERVICE_NAME "AmneziaVPN-service" CACHE STRING "Service executable name")
|
||||
endif()
|
||||
if(NOT CLIENT_ORGANIZATION_NAME)
|
||||
set(CLIENT_ORGANIZATION_NAME "AmneziaVPN.ORG" CACHE STRING "QSettings organization name")
|
||||
endif()
|
||||
if(NOT CLIENT_APP_INSTANCE_NAME)
|
||||
set(CLIENT_APP_INSTANCE_NAME "AmneziaVPNInstance" CACHE STRING "Single-instance local server name")
|
||||
endif()
|
||||
if(NOT CLIENT_KEYCHAIN_NAME)
|
||||
set(CLIENT_KEYCHAIN_NAME "${CLIENT_APPLICATION_NAME}-Keychain" CACHE STRING "QtKeychain service name used for encrypted settings keys")
|
||||
endif()
|
||||
|
||||
# -- QML entry points and UI resources
|
||||
if(NOT CLIENT_QML_ENTRYPOINT)
|
||||
set(CLIENT_QML_ENTRYPOINT "qrc:/ui/qml/main2.qml" CACHE STRING "Main QML entrypoint URL")
|
||||
endif()
|
||||
if(NOT CLIENT_QML_IMPORT_PATH)
|
||||
set(CLIENT_QML_IMPORT_PATH "qrc:/ui/qml/Modules/" CACHE STRING "Additional QQmlEngine import path")
|
||||
endif()
|
||||
if(NOT CLIENT_QML_PAGES_PREFIX)
|
||||
set(CLIENT_QML_PAGES_PREFIX "qrc:/ui/qml/Pages2/" CACHE STRING "PageController QML pages prefix")
|
||||
endif()
|
||||
if(NOT CLIENT_UI_FONT_RESOURCE)
|
||||
set(CLIENT_UI_FONT_RESOURCE ":/fonts/pt-root-ui_vf.ttf" CACHE STRING "UI font resource path")
|
||||
endif()
|
||||
if(NOT CLIENT_QML_QRC_FILE)
|
||||
set(CLIENT_QML_QRC_FILE "${_CLIENT_SRC_DIR}/ui/qml/qml.qrc" CACHE FILEPATH "QML resources manifest")
|
||||
endif()
|
||||
if(NOT CLIENT_EXTRA_QRC)
|
||||
set(CLIENT_EXTRA_QRC "" CACHE STRING "Optional semicolon-separated extra QRC files")
|
||||
endif()
|
||||
|
||||
# -- translations
|
||||
if(NOT CLIENT_TS_PREFIX)
|
||||
set(CLIENT_TS_PREFIX "amneziavpn" CACHE STRING "Translation filename prefix")
|
||||
endif()
|
||||
if(NOT CLIENT_TS_FILES)
|
||||
set(CLIENT_TS_FILES "" CACHE STRING "Optional semicolon-separated absolute TS file paths")
|
||||
endif()
|
||||
|
||||
# -- brand-provided headers
|
||||
if(NOT CLIENT_BRANDING_INCLUDE_DIR)
|
||||
set(CLIENT_BRANDING_INCLUDE_DIR "" CACHE PATH "Optional include root for non-generated branding headers (e.g. pageEnum.h)")
|
||||
endif()
|
||||
if(CLIENT_BRANDING_INCLUDE_DIR AND EXISTS "${CLIENT_BRANDING_INCLUDE_DIR}/ui/utils/pageEnum.h")
|
||||
set(CLIENT_PAGE_ENUM_HEADER "${CLIENT_BRANDING_INCLUDE_DIR}/ui/utils/pageEnum.h")
|
||||
else()
|
||||
set(CLIENT_PAGE_ENUM_HEADER "${_CLIENT_SRC_DIR}/ui/utils/pageEnum.h")
|
||||
endif()
|
||||
|
||||
if(NOT CLIENT_NOTIFICATION_IDENTIFIER)
|
||||
set(CLIENT_NOTIFICATION_IDENTIFIER "${CLIENT_TS_PREFIX}" CACHE STRING "Local notification request identifier")
|
||||
endif()
|
||||
@@ -1,45 +0,0 @@
|
||||
if(NOT CLIENT_IOS_NE_TARGET_NAME)
|
||||
set(CLIENT_IOS_NE_TARGET_NAME "networkextension" CACHE STRING "iOS network extension build target name")
|
||||
endif()
|
||||
if(NOT CLIENT_IOS_NE_ENTITLEMENTS_FILE)
|
||||
set(CLIENT_IOS_NE_ENTITLEMENTS_FILE "AmneziaVPNNetworkExtension.entitlements" CACHE STRING "iOS network extension entitlements filename")
|
||||
endif()
|
||||
if(NOT CLIENT_IOS_LAUNCHSCREEN_FILE)
|
||||
set(CLIENT_IOS_LAUNCHSCREEN_FILE "AmneziaVPNLaunchScreen.storyboard" CACHE STRING "iOS launch screen storyboard filename")
|
||||
endif()
|
||||
|
||||
get_filename_component(CLIENT_IOS_LAUNCHSCREEN_NAME "${CLIENT_IOS_LAUNCHSCREEN_FILE}" NAME_WE)
|
||||
|
||||
if(NOT CLIENT_IOS_APP_ENTITLEMENTS_PATH)
|
||||
set(CLIENT_IOS_APP_ENTITLEMENTS_PATH "${_CLIENT_SRC_DIR}/ios/app/main.entitlements" CACHE FILEPATH "iOS app entitlements file path")
|
||||
endif()
|
||||
if(NOT CLIENT_IOS_NE_ENTITLEMENTS_PATH)
|
||||
set(CLIENT_IOS_NE_ENTITLEMENTS_PATH "${_CLIENT_SRC_DIR}/ios/networkextension/${CLIENT_IOS_NE_ENTITLEMENTS_FILE}" CACHE FILEPATH "iOS network extension entitlements file path")
|
||||
endif()
|
||||
if(NOT CLIENT_IOS_LAUNCHSCREEN_PATH)
|
||||
set(CLIENT_IOS_LAUNCHSCREEN_PATH "${_CLIENT_SRC_DIR}/ios/app/${CLIENT_IOS_LAUNCHSCREEN_FILE}" CACHE FILEPATH "iOS launch screen storyboard path")
|
||||
endif()
|
||||
if(NOT CLIENT_IOS_MEDIA_ASSETS_PATH)
|
||||
set(CLIENT_IOS_MEDIA_ASSETS_PATH "${_CLIENT_SRC_DIR}/ios/app/Media.xcassets" CACHE FILEPATH "iOS app Media.xcassets path")
|
||||
endif()
|
||||
|
||||
if(NOT CLIENT_IOS_BUNDLE_ID)
|
||||
set(CLIENT_IOS_BUNDLE_ID "org.amnezia.AmneziaVPN" CACHE STRING "iOS bundle id for App Store version lookup")
|
||||
endif()
|
||||
if(NOT CLIENT_IOS_STORE_URL_FALLBACK)
|
||||
set(CLIENT_IOS_STORE_URL_FALLBACK "itms-apps://itunes.apple.com/app/id1600529900" CACHE STRING "Fallback App Store URL when lookup omits trackViewUrl")
|
||||
endif()
|
||||
|
||||
# -- signing
|
||||
if(NOT CLIENT_IOS_PROVISIONING_PROFILE_SPECIFIER)
|
||||
set(CLIENT_IOS_PROVISIONING_PROFILE_SPECIFIER "distr ios.org.amnezia.AmneziaVPN" CACHE STRING "iOS app provisioning profile specifier for release")
|
||||
endif()
|
||||
if(NOT CLIENT_IOS_PROVISIONING_PROFILE_SPECIFIER_DEBUG)
|
||||
set(CLIENT_IOS_PROVISIONING_PROFILE_SPECIFIER_DEBUG "dev ios.org.amnezia.AmneziaVPN" CACHE STRING "iOS app provisioning profile specifier for debug")
|
||||
endif()
|
||||
if(NOT CLIENT_IOS_NE_PROVISIONING_PROFILE_SPECIFIER)
|
||||
set(CLIENT_IOS_NE_PROVISIONING_PROFILE_SPECIFIER "distr ios.org.amnezia.AmneziaVPN" CACHE STRING "iOS network extension provisioning profile specifier for release")
|
||||
endif()
|
||||
if(NOT CLIENT_IOS_NE_PROVISIONING_PROFILE_SPECIFIER_DEBUG)
|
||||
set(CLIENT_IOS_NE_PROVISIONING_PROFILE_SPECIFIER_DEBUG "dev ios.org.amnezia.AmneziaVPN" CACHE STRING "iOS network extension provisioning profile specifier for debug")
|
||||
endif()
|
||||
@@ -1,37 +0,0 @@
|
||||
if(NOT CLIENT_MACOS_NE_TARGET_NAME)
|
||||
set(CLIENT_MACOS_NE_TARGET_NAME "${CLIENT_NETWORK_EXTENSION_NAME}" CACHE STRING "macOS network extension build target name")
|
||||
endif()
|
||||
if(NOT CLIENT_MACOS_NE_ENTITLEMENTS_FILE)
|
||||
set(CLIENT_MACOS_NE_ENTITLEMENTS_FILE "AmneziaVPNNetworkExtension.entitlements" CACHE STRING "macOS network extension entitlements filename")
|
||||
endif()
|
||||
|
||||
if(NOT CLIENT_MACOS_APP_ENTITLEMENTS_PATH)
|
||||
set(CLIENT_MACOS_APP_ENTITLEMENTS_PATH "${_CLIENT_SRC_DIR}/macos/app/app.entitlements" CACHE FILEPATH "macOS app entitlements file path")
|
||||
endif()
|
||||
if(NOT CLIENT_MACOS_NE_ENTITLEMENTS_PATH)
|
||||
set(CLIENT_MACOS_NE_ENTITLEMENTS_PATH "${_CLIENT_SRC_DIR}/macos/networkextension/${CLIENT_MACOS_NE_ENTITLEMENTS_FILE}" CACHE FILEPATH "macOS network extension entitlements file path")
|
||||
endif()
|
||||
if(NOT CLIENT_MACOS_MEDIA_ASSETS_PATH)
|
||||
set(CLIENT_MACOS_MEDIA_ASSETS_PATH "${_CLIENT_SRC_DIR}/macos/app/Images.xcassets" CACHE FILEPATH "macOS app Images.xcassets path")
|
||||
endif()
|
||||
if(NOT CLIENT_MACOS_APP_ICNS_PATH)
|
||||
set(CLIENT_MACOS_APP_ICNS_PATH "${_CLIENT_SRC_DIR}/images/app.icns" CACHE FILEPATH "macOS app icon (.icns) used by non-App Store builds")
|
||||
endif()
|
||||
|
||||
if(NOT CLIENT_MACOS_EXTRA_PLIST_ENTRIES)
|
||||
set(CLIENT_MACOS_EXTRA_PLIST_ENTRIES "" CACHE STRING "Extra macOS Info.plist entries appended verbatim (e.g. appearance pinning)")
|
||||
endif()
|
||||
|
||||
# -- signing
|
||||
if(NOT CLIENT_MACOS_PROVISIONING_PROFILE_SPECIFIER)
|
||||
set(CLIENT_MACOS_PROVISIONING_PROFILE_SPECIFIER "distr macos.org.amnezia.AmneziaVPN" CACHE STRING "macOS app provisioning profile specifier for release")
|
||||
endif()
|
||||
if(NOT CLIENT_MACOS_PROVISIONING_PROFILE_SPECIFIER_DEBUG)
|
||||
set(CLIENT_MACOS_PROVISIONING_PROFILE_SPECIFIER_DEBUG "dev macos.org.amnezia.AmneziaVPN" CACHE STRING "macOS app provisioning profile specifier for debug")
|
||||
endif()
|
||||
if(NOT CLIENT_MACOS_NE_PROVISIONING_PROFILE_SPECIFIER)
|
||||
set(CLIENT_MACOS_NE_PROVISIONING_PROFILE_SPECIFIER "distr macos.org.amnezia.amneziaVPN.NE" CACHE STRING "macOS network extension provisioning profile specifier for release")
|
||||
endif()
|
||||
if(NOT CLIENT_MACOS_NE_PROVISIONING_PROFILE_SPECIFIER_DEBUG)
|
||||
set(CLIENT_MACOS_NE_PROVISIONING_PROFILE_SPECIFIER_DEBUG "dev macos.org.amnezia.amneziaVPN.NE" CACHE STRING "macOS network extension provisioning profile specifier for debug")
|
||||
endif()
|
||||
@@ -1,9 +0,0 @@
|
||||
get_filename_component(_CLIENT_SRC_DIR "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE)
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/branding/common.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/branding/apple.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/branding/ios.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/branding/macos.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/branding/android.cmake)
|
||||
|
||||
unset(_CLIENT_SRC_DIR)
|
||||
@@ -24,17 +24,6 @@ set(IOS_TARGET_COMPILED_TYPES
|
||||
EXECUTABLE
|
||||
)
|
||||
|
||||
## Simulator architecture: honor CMAKE_OSX_ARCHITECTURES when set, otherwise
|
||||
## match the host — arm64 Macs run arm64 simulators (Xcode 26 has no Rosetta
|
||||
## simulator destinations), Intel Macs need x86_64.
|
||||
if(CMAKE_OSX_ARCHITECTURES)
|
||||
string(REPLACE ";" " " IOS_SIMULATOR_ARCHS "${CMAKE_OSX_ARCHITECTURES}")
|
||||
elseif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||
set(IOS_SIMULATOR_ARCHS "arm64")
|
||||
else()
|
||||
set(IOS_SIMULATOR_ARCHS "x86_64")
|
||||
endif()
|
||||
|
||||
## Inspect all the targets, and add extra properties if necessary.
|
||||
while(IOS_TARGETS)
|
||||
list(POP_FRONT IOS_TARGETS TARGET_NAME)
|
||||
@@ -49,6 +38,6 @@ while(IOS_TARGETS)
|
||||
message("Patching architectures for ${TARGET_NAME}")
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES
|
||||
XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64"
|
||||
XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "${IOS_SIMULATOR_ARCHS}"
|
||||
XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64"
|
||||
)
|
||||
endwhile()
|
||||
@@ -64,25 +64,25 @@ target_include_directories(${PROJECT} PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS})
|
||||
set_target_properties(${PROJECT} PROPERTIES
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Info.plist.in
|
||||
MACOSX_BUNDLE_ICON_FILE "AppIcon"
|
||||
MACOSX_BUNDLE_INFO_STRING "${CLIENT_APPLICATION_NAME}"
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "${CLIENT_APPLICATION_NAME}"
|
||||
MACOSX_BUNDLE_INFO_STRING "AmneziaVPN"
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "AmneziaVPN"
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}"
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION "${CMAKE_PROJECT_VERSION_TWEAK}"
|
||||
MACOSX_BUNDLE_LONG_VERSION_STRING "${APPLE_PROJECT_VERSION}-${CMAKE_PROJECT_VERSION_TWEAK}"
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "${APPLE_PROJECT_VERSION}"
|
||||
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CLIENT_IOS_APP_ENTITLEMENTS_PATH}"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/ios/app/main.entitlements"
|
||||
XCODE_ATTRIBUTE_MARKETING_VERSION "${APPLE_PROJECT_VERSION}"
|
||||
XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION "${CMAKE_PROJECT_VERSION_TWEAK}"
|
||||
XCODE_ATTRIBUTE_PRODUCT_NAME "${CLIENT_APPLICATION_NAME}"
|
||||
XCODE_ATTRIBUTE_BUNDLE_INFO_STRING "${CLIENT_APPLICATION_NAME}"
|
||||
XCODE_ATTRIBUTE_PRODUCT_NAME "AmneziaVPN"
|
||||
XCODE_ATTRIBUTE_BUNDLE_INFO_STRING "AmneziaVPN"
|
||||
XCODE_GENERATE_SCHEME TRUE
|
||||
XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon"
|
||||
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2"
|
||||
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON
|
||||
XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION
|
||||
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks"
|
||||
XCODE_EMBED_APP_EXTENSIONS ${CLIENT_IOS_NE_TARGET_NAME}
|
||||
XCODE_EMBED_APP_EXTENSIONS networkextension
|
||||
)
|
||||
|
||||
if(DEPLOY)
|
||||
@@ -90,8 +90,8 @@ if(DEPLOY)
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=Debug] "Apple Development"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_STYLE Manual
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "${CLIENT_IOS_PROVISIONING_PROFILE_SPECIFIER}"
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "${CLIENT_IOS_PROVISIONING_PROFILE_SPECIFIER_DEBUG}"
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "distr ios.org.amnezia.AmneziaVPN"
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "dev ios.org.amnezia.AmneziaVPN"
|
||||
)
|
||||
else()
|
||||
set_target_properties(${PROJECT} PROPERTIES
|
||||
@@ -103,11 +103,11 @@ set_target_properties(${PROJECT} PROPERTIES
|
||||
XCODE_ATTRIBUTE_SWIFT_VERSION "5.0"
|
||||
XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES"
|
||||
XCODE_ATTRIBUTE_SWIFT_PRECOMPILE_BRIDGING_HEADER "NO"
|
||||
XCODE_ATTRIBUTE_SWIFT_OBJC_INTERFACE_HEADER_NAME "${CLIENT_SWIFT_OBJC_HEADER_NAME}"
|
||||
XCODE_ATTRIBUTE_SWIFT_OBJC_INTERFACE_HEADER_NAME "AmneziaVPN-Swift.h"
|
||||
XCODE_ATTRIBUTE_SWIFT_OBJC_INTEROP_MODE "objcxx"
|
||||
)
|
||||
set_target_properties(${PROJECT} PROPERTIES
|
||||
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "${BUILD_VPN_DEVELOPMENT_TEAM}"
|
||||
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "X7UJ388FXK"
|
||||
)
|
||||
target_include_directories(${PROJECT} PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||
target_compile_options(${PROJECT} PRIVATE
|
||||
@@ -122,7 +122,6 @@ target_sources(${PROJECT} PRIVATE
|
||||
${WG_APPLE_SOURCE_DIR}/WireGuardKitC/x25519.c
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/LogController.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/Log.swift
|
||||
${CLIENT_GROUP_IDENTIFIER_SWIFT_FILE}
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/ScreenProtection.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/VPNCController.swift
|
||||
@@ -130,20 +129,20 @@ target_sources(${PROJECT} PRIVATE
|
||||
)
|
||||
|
||||
set_source_files_properties(
|
||||
${CLIENT_IOS_MEDIA_ASSETS_PATH}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets
|
||||
PROPERTIES MACOSX_PACKAGE_LOCATION Resources
|
||||
)
|
||||
|
||||
target_sources(${PROJECT} PRIVATE
|
||||
${CLIENT_IOS_LAUNCHSCREEN_PATH}
|
||||
${CLIENT_IOS_MEDIA_ASSETS_PATH}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/AmneziaVPNLaunchScreen.storyboard
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy
|
||||
)
|
||||
|
||||
set_property(TARGET ${PROJECT} APPEND PROPERTY RESOURCE
|
||||
${CLIENT_IOS_LAUNCHSCREEN_PATH}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/AmneziaVPNLaunchScreen.storyboard
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy
|
||||
)
|
||||
|
||||
add_subdirectory(ios/networkextension)
|
||||
add_dependencies(${PROJECT} ${CLIENT_IOS_NE_TARGET_NAME})
|
||||
add_dependencies(${PROJECT} networkextension)
|
||||
|
||||
@@ -34,8 +34,8 @@ set(SOURCES ${SOURCES}
|
||||
|
||||
|
||||
|
||||
set(ICON_FILE ${CLIENT_MACOS_APP_ICNS_PATH})
|
||||
get_filename_component(MACOSX_BUNDLE_ICON_FILE "${CLIENT_MACOS_APP_ICNS_PATH}" NAME)
|
||||
set(ICON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/images/app.icns)
|
||||
set(MACOSX_BUNDLE_ICON_FILE app.icns)
|
||||
set_source_files_properties(${ICON_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
set(SOURCES ${SOURCES} ${ICON_FILE})
|
||||
|
||||
|
||||
@@ -60,25 +60,25 @@ set_target_properties(${PROJECT} PROPERTIES
|
||||
XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/macos/app/Info.plist.in
|
||||
MACOSX_BUNDLE_ICON_FILE "AppIcon"
|
||||
MACOSX_BUNDLE_INFO_STRING "${CLIENT_APPLICATION_NAME}"
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "${CLIENT_APPLICATION_NAME}"
|
||||
MACOSX_BUNDLE_INFO_STRING "AmneziaVPN"
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "AmneziaVPN"
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}"
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION "${CMAKE_PROJECT_VERSION_TWEAK}"
|
||||
MACOSX_BUNDLE_LONG_VERSION_STRING "${APPLE_PROJECT_VERSION}-${CMAKE_PROJECT_VERSION_TWEAK}"
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "${APPLE_PROJECT_VERSION}"
|
||||
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CLIENT_MACOS_APP_ENTITLEMENTS_PATH}"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/macos/app/app.entitlements"
|
||||
XCODE_ATTRIBUTE_MARKETING_VERSION "${APPLE_PROJECT_VERSION}"
|
||||
XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION "${CMAKE_PROJECT_VERSION_TWEAK}"
|
||||
XCODE_ATTRIBUTE_PRODUCT_NAME "${CLIENT_APPLICATION_NAME}"
|
||||
XCODE_ATTRIBUTE_BUNDLE_INFO_STRING "${CLIENT_APPLICATION_NAME}"
|
||||
XCODE_ATTRIBUTE_PRODUCT_NAME "AmneziaVPN"
|
||||
XCODE_ATTRIBUTE_BUNDLE_INFO_STRING "AmneziaVPN"
|
||||
XCODE_GENERATE_SCHEME TRUE
|
||||
XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon"
|
||||
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY "NO"
|
||||
XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY "YES"
|
||||
|
||||
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks"
|
||||
XCODE_EMBED_APP_EXTENSIONS ${CLIENT_MACOS_NE_TARGET_NAME}
|
||||
XCODE_EMBED_APP_EXTENSIONS AmneziaVPNNetworkExtension
|
||||
)
|
||||
|
||||
if(DEPLOY)
|
||||
@@ -86,8 +86,8 @@ if(DEPLOY)
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=Debug] "Apple Development"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_STYLE Manual
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "${CLIENT_MACOS_PROVISIONING_PROFILE_SPECIFIER}"
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "${CLIENT_MACOS_PROVISIONING_PROFILE_SPECIFIER_DEBUG}"
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "distr macos.org.amnezia.AmneziaVPN"
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "dev macos.org.amnezia.AmneziaVPN"
|
||||
)
|
||||
else()
|
||||
set_target_properties(${PROJECT} PROPERTIES
|
||||
@@ -99,11 +99,11 @@ set_target_properties(${PROJECT} PROPERTIES
|
||||
XCODE_ATTRIBUTE_SWIFT_VERSION "5.0"
|
||||
XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES"
|
||||
XCODE_ATTRIBUTE_SWIFT_PRECOMPILE_BRIDGING_HEADER "NO"
|
||||
XCODE_ATTRIBUTE_SWIFT_OBJC_INTERFACE_HEADER_NAME "${CLIENT_SWIFT_OBJC_HEADER_NAME}"
|
||||
XCODE_ATTRIBUTE_SWIFT_OBJC_INTERFACE_HEADER_NAME "AmneziaVPN-Swift.h"
|
||||
XCODE_ATTRIBUTE_SWIFT_OBJC_INTEROP_MODE "objcxx"
|
||||
)
|
||||
set_target_properties(${PROJECT} PROPERTIES
|
||||
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "${BUILD_VPN_DEVELOPMENT_TEAM}"
|
||||
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "X7UJ388FXK"
|
||||
)
|
||||
target_include_directories(${PROJECT} PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||
target_compile_options(${PROJECT} PRIVATE
|
||||
@@ -117,7 +117,6 @@ target_sources(${PROJECT} PRIVATE
|
||||
${WG_APPLE_SOURCE_DIR}/WireGuardKitC/x25519.c
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/LogController.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/Log.swift
|
||||
${CLIENT_GROUP_IDENTIFIER_SWIFT_FILE}
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/ScreenProtection.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/VPNCController.swift
|
||||
@@ -125,12 +124,12 @@ target_sources(${PROJECT} PRIVATE
|
||||
)
|
||||
|
||||
set_source_files_properties(
|
||||
${CLIENT_MACOS_MEDIA_ASSETS_PATH}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/macos/app/Images.xcassets
|
||||
PROPERTIES MACOSX_PACKAGE_LOCATION Resources
|
||||
)
|
||||
|
||||
target_sources(${PROJECT} PRIVATE
|
||||
${CLIENT_MACOS_MEDIA_ASSETS_PATH}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/macos/app/Images.xcassets
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy
|
||||
)
|
||||
|
||||
@@ -139,7 +138,7 @@ set_property(TARGET ${PROJECT} APPEND PROPERTY RESOURCE
|
||||
)
|
||||
|
||||
add_subdirectory(macos/networkextension)
|
||||
add_dependencies(${PROJECT} ${CLIENT_MACOS_NE_TARGET_NAME})
|
||||
add_dependencies(${PROJECT} AmneziaVPNNetworkExtension)
|
||||
|
||||
get_target_property(QtCore_location Qt6::Core LOCATION)
|
||||
message("QtCore_location")
|
||||
@@ -148,5 +147,5 @@ message(${QtCore_location})
|
||||
get_filename_component(QT_BIN_DIR_DETECTED "${QtCore_location}/../../../../../bin" ABSOLUTE)
|
||||
|
||||
add_custom_command(TARGET ${PROJECT} POST_BUILD
|
||||
COMMAND ${QT_BIN_DIR_DETECTED}/macdeployqt $<TARGET_BUNDLE_DIR:${PROJECT}> -appstore-compliant -qmldir=${CMAKE_CURRENT_SOURCE_DIR} -no-codesign
|
||||
COMMAND ${QT_BIN_DIR_DETECTED}/macdeployqt $<TARGET_BUNDLE_DIR:AmneziaVPN> -appstore-compliant -qmldir=${CMAKE_CURRENT_SOURCE_DIR} -no-codesign
|
||||
)
|
||||
|
||||
@@ -51,7 +51,6 @@ set(HEADERS ${HEADERS}
|
||||
${CLIENT_ROOT_DIR}/core/repositories/secureAppSettingsRepository.h
|
||||
${CLIENT_ROOT_DIR}/core/protocols/qmlRegisterProtocols.h
|
||||
${CLIENT_ROOT_DIR}/ui/utils/pages.h
|
||||
${CLIENT_PAGE_ENUM_HEADER}
|
||||
${CLIENT_ROOT_DIR}/ui/utils/qAutoStart.h
|
||||
${CLIENT_ROOT_DIR}/ui/utils/mtProxyPublicHostInput.h
|
||||
${CLIENT_ROOT_DIR}/core/protocols/vpnProtocol.h
|
||||
@@ -65,9 +64,7 @@ set(HEADERS ${HEADERS}
|
||||
${CLIENT_ROOT_DIR}/../common/crypto/cryptoUtils.h
|
||||
${CLIENT_ROOT_DIR}/ui/utils/qmlUtils.h
|
||||
${CLIENT_ROOT_DIR}/core/utils/api/apiUtils.h
|
||||
${CLIENT_ROOT_DIR}/core/utils/api/gatewayPayloadBuilder.h
|
||||
${CLIENT_ROOT_DIR}/core/utils/osSignalHandler.h
|
||||
${CLIENT_ROOT_DIR}/core/utils/swiftBridge.h
|
||||
${CLIENT_ROOT_DIR}/core/utils/utilities.h
|
||||
${CLIENT_ROOT_DIR}/core/utils/managementServer.h
|
||||
${CLIENT_ROOT_DIR}/core/utils/constants.h
|
||||
@@ -150,7 +147,6 @@ set(SOURCES ${SOURCES}
|
||||
${CLIENT_ROOT_DIR}/../common/crypto/cryptoUtils.cpp
|
||||
${CLIENT_ROOT_DIR}/ui/utils/qmlUtils.cpp
|
||||
${CLIENT_ROOT_DIR}/core/utils/api/apiUtils.cpp
|
||||
${CLIENT_ROOT_DIR}/core/utils/api/gatewayPayloadBuilder.cpp
|
||||
${CLIENT_ROOT_DIR}/core/utils/serverConfigUtils.cpp
|
||||
${CLIENT_ROOT_DIR}/core/utils/osSignalHandler.cpp
|
||||
${CLIENT_ROOT_DIR}/core/utils/utilities.cpp
|
||||
|
||||
@@ -106,8 +106,6 @@ ProtocolConfig AwgConfigurator::createConfig(const ServerCredentials &credential
|
||||
newClientConfig.rejectAfterTime = configMap.value(configKey::rejectAfterTime);
|
||||
newClientConfig.keepaliveTimeout = configMap.value(configKey::keepaliveTimeout);
|
||||
newClientConfig.maxHandshakeAttempts = configMap.value(configKey::maxHandshakeAttempts);
|
||||
newClientConfig.randomTrailers = configMap.value(configKey::randomTrailers);
|
||||
newClientConfig.disableCookies = configMap.value(configKey::disableCookies);
|
||||
|
||||
protocolConfig.setClientConfig(newClientConfig);
|
||||
|
||||
|
||||
@@ -228,6 +228,8 @@ ProtocolConfig WireguardConfigurator::createConfig(const ServerCredentials &cred
|
||||
}
|
||||
}
|
||||
|
||||
const bool isAwg3 = awgServerConfig && awgServerConfig->protocolVersion == protocols::awg::awgV3;
|
||||
|
||||
amnezia::ScriptVars vars = amnezia::genBaseVars(credentials, container, dnsSettings.primaryDns, dnsSettings.secondaryDns);
|
||||
vars.append(amnezia::genProtocolVarsForContainer(container, containerConfig));
|
||||
QString scriptData = amnezia::scriptData(m_configTemplate, container);
|
||||
@@ -273,9 +275,8 @@ ProtocolConfig WireguardConfigurator::createConfig(const ServerCredentials &cred
|
||||
clientConfig.presharedKey = connData.pskKey;
|
||||
clientConfig.clientId = connData.clientPubKey;
|
||||
clientConfig.allowedIps = QStringList { "0.0.0.0/0", "::/0" };
|
||||
const bool useKeepAliveRange = awgServerConfig && awgServerConfig->hasAwg3Params();
|
||||
clientConfig.persistentKeepAlive = useKeepAliveRange ? protocols::awg::defaultPersistentKeepAlive
|
||||
: protocols::wireguard::defaultPersistentKeepAlive;
|
||||
clientConfig.persistentKeepAlive = isAwg3 ? protocols::awg::defaultPersistentKeepAlive
|
||||
: protocols::wireguard::defaultPersistentKeepAlive;
|
||||
clientConfig.mtu = mtu;
|
||||
clientConfig.isObfuscationEnabled = false;
|
||||
|
||||
|
||||
@@ -211,6 +211,33 @@ ErrorCode XrayConfigurator::readRealityKeyFiles(const DockerContainer container,
|
||||
return readKeyFile(QString::fromLatin1(amnezia::protocols::xray::shortidPath), outShortId);
|
||||
}
|
||||
|
||||
QJsonObject XrayConfigurator::mergeStreamSettingsForServerInbound(const XrayServerConfig &srv,
|
||||
const QJsonObject &existingStreamSettings) const
|
||||
{
|
||||
QJsonObject streamSettings = buildStreamSettings(srv, QString());
|
||||
|
||||
if (effectiveSecurity(srv) != QLatin1String("reality")) {
|
||||
return streamSettings;
|
||||
}
|
||||
|
||||
const QJsonObject newRs = streamSettings[amnezia::protocols::xray::realitySettings].toObject();
|
||||
QJsonObject oldRs = existingStreamSettings[amnezia::protocols::xray::realitySettings].toObject();
|
||||
QJsonObject merged = oldRs.isEmpty() ? newRs : oldRs;
|
||||
|
||||
const QString siteEff = srv.site.isEmpty() ? QString::fromLatin1(amnezia::protocols::xray::defaultSite) : srv.site;
|
||||
const QString sniEff = srv.sni.isEmpty() ? siteEff : srv.sni;
|
||||
|
||||
if (newRs.contains(amnezia::protocols::xray::fingerprint)) {
|
||||
merged[amnezia::protocols::xray::fingerprint] = newRs[amnezia::protocols::xray::fingerprint];
|
||||
}
|
||||
merged[amnezia::protocols::xray::serverNames] = QJsonArray { sniEff };
|
||||
if (!merged.contains(QStringLiteral("dest"))) {
|
||||
merged[QStringLiteral("dest")] = siteEff + QStringLiteral(":443");
|
||||
}
|
||||
|
||||
streamSettings[amnezia::protocols::xray::realitySettings] = merged;
|
||||
return streamSettings;
|
||||
}
|
||||
|
||||
ErrorCode XrayConfigurator::applyServerSettingsToRemote(const ServerCredentials &credentials, DockerContainer container,
|
||||
ContainerConfig &containerConfig, const DnsSettings &dnsSettings,
|
||||
@@ -281,6 +308,13 @@ ErrorCode XrayConfigurator::applyServerSettingsToRemote(const ServerCredentials
|
||||
return ErrorCode::XrayServerConfigInvalid;
|
||||
}
|
||||
|
||||
const QJsonObject existingStream = inbound[amnezia::protocols::xray::streamSettings].toObject();
|
||||
inbound[amnezia::protocols::xray::streamSettings] = mergeStreamSettingsForServerInbound(srv, existingStream);
|
||||
|
||||
if (!srv.port.isEmpty()) {
|
||||
inbound[amnezia::protocols::xray::port] = srv.port.toInt();
|
||||
}
|
||||
|
||||
QJsonObject settings = inbound[amnezia::protocols::xray::settings].toObject();
|
||||
if (!settings.contains(amnezia::protocols::xray::clients)) {
|
||||
settings[amnezia::protocols::xray::clients] = QJsonArray {};
|
||||
|
||||
@@ -60,6 +60,9 @@ private:
|
||||
QString &outPublicKey,
|
||||
QString &outShortId) const;
|
||||
|
||||
QJsonObject mergeStreamSettingsForServerInbound(const amnezia::XrayServerConfig &srv,
|
||||
const QJsonObject &existingStreamSettings) const;
|
||||
|
||||
QJsonObject buildStreamSettings(const amnezia::XrayServerConfig &srv,
|
||||
const QString &clientId) const;
|
||||
};
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "core/controllers/gatewayController.h"
|
||||
#include "core/repositories/secureServersRepository.h"
|
||||
#include "core/utils/api/apiUtils.h"
|
||||
#include "core/utils/api/gatewayPayloadBuilder.h"
|
||||
#include "core/utils/constants/apiKeys.h"
|
||||
#include "core/utils/constants/apiConstants.h"
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
@@ -83,12 +81,15 @@ QFuture<QPair<ErrorCode, QJsonArray>> NewsController::fetchNews()
|
||||
m_appSettingsRepository->isStrictKillSwitchEnabled(),
|
||||
m_appSettingsRepository);
|
||||
|
||||
// both country codes and service types are arrays here, one entry per gateway stack the user has
|
||||
const QJsonObject payload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::locale, apiUtils::getAppLanguageCode(m_appSettingsRepository))
|
||||
.addField(apiDefs::key::userCountryCode, services.value(apiDefs::key::userCountryCode))
|
||||
.addField(apiDefs::key::serviceType, services.value(apiDefs::key::serviceType))
|
||||
.build();
|
||||
QJsonObject payload;
|
||||
payload.insert("locale", m_appSettingsRepository->getAppLanguage().name().split("_").first());
|
||||
|
||||
if (services.contains(apiDefs::key::userCountryCode)) {
|
||||
payload.insert(apiDefs::key::userCountryCode, services.value(apiDefs::key::userCountryCode));
|
||||
}
|
||||
if (services.contains(apiDefs::key::serviceType)) {
|
||||
payload.insert(apiDefs::key::serviceType, services.value(apiDefs::key::serviceType));
|
||||
}
|
||||
|
||||
auto future = gatewayController->postAsync(QString("%1v1/news"), payload);
|
||||
return future.then([gatewayController](QPair<ErrorCode, QByteArray> result) -> QPair<ErrorCode, QJsonArray> {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "servicesCatalogController.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QSysInfo>
|
||||
#include <QJsonArray>
|
||||
#include <QEventLoop>
|
||||
#include <QDebug>
|
||||
@@ -10,7 +11,6 @@
|
||||
#include <limits>
|
||||
|
||||
#include "core/controllers/gatewayController.h"
|
||||
#include "core/utils/api/gatewayPayloadBuilder.h"
|
||||
#include "core/utils/serverConfigUtils.h"
|
||||
#include "core/utils/constants/apiKeys.h"
|
||||
#include "core/utils/constants/apiConstants.h"
|
||||
@@ -212,7 +212,11 @@ ServicesCatalogController::ServicesCatalogController(SecureAppSettingsRepository
|
||||
|
||||
ErrorCode ServicesCatalogController::fillAvailableServices(QJsonObject &servicesData)
|
||||
{
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository).build();
|
||||
QJsonObject apiPayload;
|
||||
apiPayload[apiDefs::key::osVersion] = QSysInfo::productType();
|
||||
apiPayload[apiDefs::key::appVersion] = QString(APP_VERSION);
|
||||
apiPayload[apiDefs::key::cliName] = QString(APPLICATION_NAME);
|
||||
apiPayload[apiDefs::key::appLanguage] = m_appSettingsRepository->getAppLanguage().name().split("_").first();
|
||||
|
||||
QByteArray responseBody;
|
||||
ErrorCode errorCode = executeRequest(QString("%1v1/services"), apiPayload, responseBody);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <QJsonObject>
|
||||
#include <QPromise>
|
||||
#include <QSet>
|
||||
#include <QSysInfo>
|
||||
#include <QUuid>
|
||||
#include <QVariantMap>
|
||||
|
||||
@@ -20,7 +21,6 @@
|
||||
#include "core/utils/constants/apiKeys.h"
|
||||
#include "core/utils/constants/apiConstants.h"
|
||||
#include "core/utils/api/apiUtils.h"
|
||||
#include "core/utils/api/gatewayPayloadBuilder.h"
|
||||
#include "core/controllers/gatewayController.h"
|
||||
#include "core/utils/protocolEnum.h"
|
||||
#include "core/protocols/protocolUtils.h"
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
#if defined(Q_OS_IOS) || defined(MACOS_NE)
|
||||
#include "platforms/ios/ios_controller.h"
|
||||
#include "core/utils/swiftBridge.h"
|
||||
#include <AmneziaVPN-Swift.h>
|
||||
#endif
|
||||
|
||||
using namespace amnezia;
|
||||
@@ -97,6 +97,39 @@ SubscriptionController::SubscriptionController(SecureServersRepository* serversR
|
||||
{
|
||||
}
|
||||
|
||||
QJsonObject SubscriptionController::GatewayRequestData::toJsonObject() const
|
||||
{
|
||||
QJsonObject obj;
|
||||
if (!osVersion.isEmpty()) {
|
||||
obj[apiDefs::key::osVersion] = osVersion;
|
||||
}
|
||||
if (!appVersion.isEmpty()) {
|
||||
obj[apiDefs::key::appVersion] = appVersion;
|
||||
}
|
||||
if (!appLanguage.isEmpty()) {
|
||||
obj[apiDefs::key::appLanguage] = appLanguage;
|
||||
}
|
||||
if (!installationUuid.isEmpty()) {
|
||||
obj[apiDefs::key::uuid] = installationUuid;
|
||||
}
|
||||
if (!userCountryCode.isEmpty()) {
|
||||
obj[apiDefs::key::userCountryCode] = userCountryCode;
|
||||
}
|
||||
if (!serverCountryCode.isEmpty()) {
|
||||
obj[apiDefs::key::serverCountryCode] = serverCountryCode;
|
||||
}
|
||||
if (!serviceType.isEmpty()) {
|
||||
obj[apiDefs::key::serviceType] = serviceType;
|
||||
}
|
||||
if (!serviceProtocol.isEmpty()) {
|
||||
obj[apiDefs::key::serviceProtocol] = serviceProtocol;
|
||||
}
|
||||
if (!authData.isEmpty()) {
|
||||
obj[apiDefs::key::authData] = authData;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
SubscriptionController::ProtocolData SubscriptionController::generateProtocolData(const QString &protocol)
|
||||
{
|
||||
ProtocolData protocolData;
|
||||
@@ -111,15 +144,13 @@ SubscriptionController::ProtocolData SubscriptionController::generateProtocolDat
|
||||
return protocolData;
|
||||
}
|
||||
|
||||
QString SubscriptionController::publicKeyForProtocol(const QString &protocol, const ProtocolData &protocolData)
|
||||
void SubscriptionController::appendProtocolDataToApiPayload(const QString &protocol, const ProtocolData &protocolData, QJsonObject &apiPayload)
|
||||
{
|
||||
if (protocol == configKey::awg) {
|
||||
return protocolData.wireGuardClientPubKey;
|
||||
apiPayload[apiDefs::key::publicKey] = protocolData.wireGuardClientPubKey;
|
||||
} else if (protocol == configKey::vless) {
|
||||
apiPayload[apiDefs::key::publicKey] = protocolData.xrayUuid;
|
||||
}
|
||||
if (protocol == configKey::vless) {
|
||||
return protocolData.xrayUuid;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorCode SubscriptionController::extractServerConfigJsonFromResponse(const QByteArray &apiResponseBody, const QString &protocol,
|
||||
@@ -209,12 +240,18 @@ ErrorCode SubscriptionController::importServiceFromGateway(const QString &userCo
|
||||
const QString &serviceProtocol, const ProtocolData &protocolData,
|
||||
CaptchaInfo &captchaInfo)
|
||||
{
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::userCountryCode, userCountryCode)
|
||||
.addField(apiDefs::key::serviceType, serviceType)
|
||||
.addField(apiDefs::key::serviceProtocol, serviceProtocol)
|
||||
.addField(apiDefs::key::publicKey, publicKeyForProtocol(serviceProtocol, protocolData))
|
||||
.build();
|
||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
||||
QString(APP_VERSION),
|
||||
m_appSettingsRepository->getAppLanguage().name().split("_").first(),
|
||||
m_appSettingsRepository->getInstallationUuid(true),
|
||||
userCountryCode,
|
||||
"",
|
||||
serviceType,
|
||||
serviceProtocol,
|
||||
QJsonObject() };
|
||||
|
||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
||||
appendProtocolDataToApiPayload(serviceProtocol, protocolData, apiPayload);
|
||||
|
||||
QByteArray responseBody;
|
||||
ErrorCode errorCode = executeRequest(QString("%1v1/config"), apiPayload, responseBody);
|
||||
@@ -254,15 +291,20 @@ ErrorCode SubscriptionController::importTrialFromGateway(const QString &userCoun
|
||||
return ErrorCode::ApiConfigEmptyError;
|
||||
}
|
||||
|
||||
ProtocolData protocolData = generateProtocolData(serviceProtocol);
|
||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
||||
QString(APP_VERSION),
|
||||
m_appSettingsRepository->getAppLanguage().name().split("_").first(),
|
||||
m_appSettingsRepository->getInstallationUuid(true),
|
||||
userCountryCode,
|
||||
"",
|
||||
serviceType,
|
||||
serviceProtocol,
|
||||
QJsonObject() };
|
||||
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::userCountryCode, userCountryCode)
|
||||
.addField(apiDefs::key::serviceType, serviceType)
|
||||
.addField(apiDefs::key::serviceProtocol, serviceProtocol)
|
||||
.addField(apiDefs::key::publicKey, publicKeyForProtocol(serviceProtocol, protocolData))
|
||||
.addField(apiDefs::key::email, trimmedEmail)
|
||||
.build();
|
||||
ProtocolData protocolData = generateProtocolData(serviceProtocol);
|
||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
||||
appendProtocolDataToApiPayload(serviceProtocol, protocolData, apiPayload);
|
||||
apiPayload.insert(apiDefs::key::email, trimmedEmail);
|
||||
|
||||
QByteArray responseBody;
|
||||
ErrorCode errorCode = executeRequest(QString("%1v1/trial"), apiPayload, responseBody);
|
||||
@@ -303,13 +345,19 @@ ErrorCode SubscriptionController::importServiceFromAppStore(const QString &userC
|
||||
const QString &transactionId, bool isTestPurchase,
|
||||
int *duplicateServerIndex)
|
||||
{
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::userCountryCode, userCountryCode)
|
||||
.addField(apiDefs::key::serviceType, serviceType)
|
||||
.addField(apiDefs::key::serviceProtocol, serviceProtocol)
|
||||
.addField(apiDefs::key::publicKey, publicKeyForProtocol(serviceProtocol, protocolData))
|
||||
.addField(apiDefs::key::transactionId, transactionId)
|
||||
.build();
|
||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
||||
QString(APP_VERSION),
|
||||
m_appSettingsRepository->getAppLanguage().name().split("_").first(),
|
||||
m_appSettingsRepository->getInstallationUuid(true),
|
||||
userCountryCode,
|
||||
"",
|
||||
serviceType,
|
||||
serviceProtocol,
|
||||
QJsonObject() };
|
||||
|
||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
||||
appendProtocolDataToApiPayload(serviceProtocol, protocolData, apiPayload);
|
||||
apiPayload[apiDefs::key::transactionId] = transactionId;
|
||||
|
||||
QByteArray responseBody;
|
||||
ErrorCode errorCode = executeRequest(QString("%1v1/subscriptions"), apiPayload, responseBody, isTestPurchase);
|
||||
@@ -364,6 +412,8 @@ ErrorCode SubscriptionController::importServiceFromAppStore(const QString &userC
|
||||
ApiV2ServerConfig apiV2ServerConfig = ApiV2ServerConfig::fromJson(configObject);
|
||||
ApiV2ServerConfig* apiV2 = &apiV2ServerConfig;
|
||||
apiV2->apiConfig.vpnKey = normalizedKey;
|
||||
apiV2->apiConfig.isTestPurchase = isTestPurchase;
|
||||
apiV2->apiConfig.isInAppPurchase = true;
|
||||
apiV2->apiConfig.subscriptionExpiredByServer = false;
|
||||
apiV2->crc = crc;
|
||||
|
||||
@@ -401,15 +451,23 @@ ErrorCode SubscriptionController::updateServiceFromGateway(const QString &server
|
||||
|
||||
ProtocolData protocolData = generateProtocolData(serviceProtocol);
|
||||
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::userCountryCode, apiV2->apiConfig.userCountryCode)
|
||||
.addField(apiDefs::key::serverCountryCode, newCountryCode)
|
||||
.addField(apiDefs::key::serviceType, apiV2->serviceType())
|
||||
.addField(apiDefs::key::serviceProtocol, serviceProtocol)
|
||||
.addField(apiDefs::key::publicKey, publicKeyForProtocol(serviceProtocol, protocolData))
|
||||
.addField(apiDefs::key::authData, apiV2->authData.toJson())
|
||||
.addField(apiDefs::key::isConnectEvent, isConnectEvent ? QJsonValue(true) : QJsonValue())
|
||||
.build();
|
||||
QJsonObject authDataJson = apiV2->authData.toJson();
|
||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
||||
QString(APP_VERSION),
|
||||
m_appSettingsRepository->getAppLanguage().name().split("_").first(),
|
||||
m_appSettingsRepository->getInstallationUuid(true),
|
||||
apiV2->apiConfig.userCountryCode,
|
||||
newCountryCode,
|
||||
apiV2->serviceType(),
|
||||
serviceProtocol,
|
||||
authDataJson };
|
||||
|
||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
||||
appendProtocolDataToApiPayload(serviceProtocol, protocolData, apiPayload);
|
||||
|
||||
if (isConnectEvent) {
|
||||
apiPayload[apiDefs::key::isConnectEvent] = true;
|
||||
}
|
||||
|
||||
QByteArray responseBody;
|
||||
ErrorCode errorCode = executeRequest(QString("%1v1/config"), apiPayload, responseBody, isTestPurchase);
|
||||
@@ -455,6 +513,8 @@ ErrorCode SubscriptionController::applyUpdatedServiceConfig(const QString &serve
|
||||
ApiV2ServerConfig* newApiV2 = &newApiV2Config;
|
||||
|
||||
newApiV2->apiConfig.vpnKey = apiV2->apiConfig.vpnKey;
|
||||
newApiV2->apiConfig.isTestPurchase = apiV2->apiConfig.isTestPurchase;
|
||||
newApiV2->apiConfig.isInAppPurchase = apiV2->apiConfig.isInAppPurchase;
|
||||
newApiV2->apiConfig.subscriptionExpiredByServer = false;
|
||||
|
||||
newApiV2->authData = apiV2->authData;
|
||||
@@ -483,17 +543,26 @@ ErrorCode SubscriptionController::resolveUpdateServiceCaptcha(const QString &ser
|
||||
const bool isTestPurchase = apiV2->apiConfig.isTestPurchase;
|
||||
QString serviceProtocol = apiV2->serviceProtocol();
|
||||
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::userCountryCode, apiV2->apiConfig.userCountryCode)
|
||||
.addField(apiDefs::key::serverCountryCode, newCountryCode)
|
||||
.addField(apiDefs::key::serviceType, apiV2->serviceType())
|
||||
.addField(apiDefs::key::serviceProtocol, serviceProtocol)
|
||||
.addField(apiDefs::key::publicKey, publicKeyForProtocol(serviceProtocol, protocolData))
|
||||
.addField(apiDefs::key::authData, apiV2->authData.toJson())
|
||||
.addField(apiDefs::key::captchaId, captchaId)
|
||||
.addField(apiDefs::key::captchaSolution, normalizeCaptchaSolution(captchaSolution))
|
||||
.addField(apiDefs::key::isConnectEvent, isConnectEvent ? QJsonValue(true) : QJsonValue())
|
||||
.build();
|
||||
QJsonObject authDataJson = apiV2->authData.toJson();
|
||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
||||
QString(APP_VERSION),
|
||||
m_appSettingsRepository->getAppLanguage().name().split("_").first(),
|
||||
m_appSettingsRepository->getInstallationUuid(true),
|
||||
apiV2->apiConfig.userCountryCode,
|
||||
newCountryCode,
|
||||
apiV2->serviceType(),
|
||||
serviceProtocol,
|
||||
authDataJson };
|
||||
|
||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
||||
appendProtocolDataToApiPayload(serviceProtocol, protocolData, apiPayload);
|
||||
|
||||
if (isConnectEvent) {
|
||||
apiPayload[apiDefs::key::isConnectEvent] = true;
|
||||
}
|
||||
|
||||
apiPayload["captcha_id"] = captchaId;
|
||||
apiPayload["captcha_solution"] = normalizeCaptchaSolution(captchaSolution);
|
||||
|
||||
QByteArray responseBody;
|
||||
ErrorCode errorCode = executeRequest(QString("%1v1/config"), apiPayload, responseBody, isTestPurchase);
|
||||
@@ -526,12 +595,18 @@ ErrorCode SubscriptionController::deactivateDevice(const QString &serverId)
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::userCountryCode, apiV2->apiConfig.userCountryCode)
|
||||
.addField(apiDefs::key::serverCountryCode, apiV2->apiConfig.serverCountryCode)
|
||||
.addField(apiDefs::key::serviceType, apiV2->serviceType())
|
||||
.addField(apiDefs::key::authData, apiV2->authData.toJson())
|
||||
.build();
|
||||
QJsonObject authDataJson = apiV2->authData.toJson();
|
||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
||||
QString(APP_VERSION),
|
||||
m_appSettingsRepository->getAppLanguage().name().split("_").first(),
|
||||
m_appSettingsRepository->getInstallationUuid(true),
|
||||
apiV2->apiConfig.userCountryCode,
|
||||
apiV2->apiConfig.serverCountryCode,
|
||||
apiV2->serviceType(),
|
||||
"",
|
||||
authDataJson };
|
||||
|
||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
||||
|
||||
const bool isTestPurchase = apiV2->apiConfig.isTestPurchase;
|
||||
QByteArray responseBody;
|
||||
@@ -557,13 +632,18 @@ ErrorCode SubscriptionController::deactivateExternalDevice(const QString &server
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::installationUuid, uuid)
|
||||
.addField(apiDefs::key::userCountryCode, apiV2->apiConfig.userCountryCode)
|
||||
.addField(apiDefs::key::serverCountryCode, serverCountryCode)
|
||||
.addField(apiDefs::key::serviceType, apiV2->serviceType())
|
||||
.addField(apiDefs::key::authData, apiV2->authData.toJson())
|
||||
.build();
|
||||
QJsonObject authDataJson = apiV2->authData.toJson();
|
||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
||||
QString(APP_VERSION),
|
||||
m_appSettingsRepository->getAppLanguage().name().split("_").first(),
|
||||
uuid,
|
||||
apiV2->apiConfig.userCountryCode,
|
||||
serverCountryCode,
|
||||
apiV2->serviceType(),
|
||||
"",
|
||||
authDataJson };
|
||||
|
||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
||||
|
||||
const bool isTestPurchase = apiV2->apiConfig.isTestPurchase;
|
||||
QByteArray responseBody;
|
||||
@@ -591,14 +671,19 @@ ErrorCode SubscriptionController::exportNativeConfig(const QString &serverId, co
|
||||
QString protocol = configKey::awg;
|
||||
ProtocolData protocolData = generateProtocolData(protocol);
|
||||
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::userCountryCode, apiV2->apiConfig.userCountryCode)
|
||||
.addField(apiDefs::key::serverCountryCode, serverCountryCode)
|
||||
.addField(apiDefs::key::serviceType, apiV2->serviceType())
|
||||
.addField(apiDefs::key::serviceProtocol, protocol)
|
||||
.addField(apiDefs::key::publicKey, publicKeyForProtocol(protocol, protocolData))
|
||||
.addField(apiDefs::key::authData, apiV2->authData.toJson())
|
||||
.build();
|
||||
QJsonObject authDataJson = apiV2->authData.toJson();
|
||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
||||
QString(APP_VERSION),
|
||||
m_appSettingsRepository->getAppLanguage().name().split("_").first(),
|
||||
m_appSettingsRepository->getInstallationUuid(true),
|
||||
apiV2->apiConfig.userCountryCode,
|
||||
serverCountryCode,
|
||||
apiV2->serviceType(),
|
||||
protocol,
|
||||
authDataJson };
|
||||
|
||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
||||
appendProtocolDataToApiPayload(protocol, protocolData, apiPayload);
|
||||
|
||||
QByteArray responseBody;
|
||||
ErrorCode errorCode = executeRequest(QString("%1v1/native_config"), apiPayload, responseBody, isTestPurchase);
|
||||
@@ -621,13 +706,18 @@ ErrorCode SubscriptionController::revokeNativeConfig(const QString &serverId, co
|
||||
const bool isTestPurchase = apiV2->apiConfig.isTestPurchase;
|
||||
QString protocol = configKey::awg;
|
||||
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::userCountryCode, apiV2->apiConfig.userCountryCode)
|
||||
.addField(apiDefs::key::serverCountryCode, serverCountryCode)
|
||||
.addField(apiDefs::key::serviceType, apiV2->serviceType())
|
||||
.addField(apiDefs::key::serviceProtocol, protocol)
|
||||
.addField(apiDefs::key::authData, apiV2->authData.toJson())
|
||||
.build();
|
||||
QJsonObject authDataJson = apiV2->authData.toJson();
|
||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
||||
QString(APP_VERSION),
|
||||
m_appSettingsRepository->getAppLanguage().name().split("_").first(),
|
||||
m_appSettingsRepository->getInstallationUuid(true),
|
||||
apiV2->apiConfig.userCountryCode,
|
||||
serverCountryCode,
|
||||
apiV2->serviceType(),
|
||||
protocol,
|
||||
authDataJson };
|
||||
|
||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
||||
|
||||
QByteArray responseBody;
|
||||
ErrorCode errorCode = executeRequest(QString("%1v1/revoke_native_config"), apiPayload, responseBody, isTestPurchase);
|
||||
@@ -692,7 +782,7 @@ void SubscriptionController::removeApiConfig(const QString &serverId)
|
||||
.arg(hostName)
|
||||
.arg("");
|
||||
|
||||
SWIFT_BRIDGE_NAMESPACE::removeVPNC(vpncName.toStdString());
|
||||
AmneziaVPN::removeVPNC(vpncName.toStdString());
|
||||
#endif
|
||||
|
||||
apiV2->dns1.clear();
|
||||
@@ -934,13 +1024,20 @@ ErrorCode SubscriptionController::getAccountInfo(const QString &serverId, QJsonO
|
||||
}
|
||||
bool isTestPurchase = apiV2->apiConfig.isTestPurchase;
|
||||
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::userCountryCode, apiV2->apiConfig.userCountryCode)
|
||||
.addField(apiDefs::key::serviceType, apiV2->serviceType())
|
||||
.addField(apiDefs::key::authData, apiV2->authData.toJson())
|
||||
.addField(apiDefs::key::cliVersion, QString(APP_VERSION))
|
||||
.addField(apiDefs::key::subscriptionStatus, getSubscriptionStatusForRenewal(apiV2->apiConfig))
|
||||
.build();
|
||||
QJsonObject authDataJson = apiV2->authData.toJson();
|
||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
||||
QString(APP_VERSION),
|
||||
m_appSettingsRepository->getAppLanguage().name().split("_").first(),
|
||||
m_appSettingsRepository->getInstallationUuid(true),
|
||||
apiV2->apiConfig.userCountryCode,
|
||||
"",
|
||||
apiV2->serviceType(),
|
||||
"",
|
||||
authDataJson };
|
||||
|
||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
||||
apiPayload[apiDefs::key::cliVersion] = QString(APP_VERSION);
|
||||
apiPayload[apiDefs::key::subscriptionStatus] = getSubscriptionStatusForRenewal(apiV2->apiConfig);
|
||||
|
||||
QByteArray responseBody;
|
||||
ErrorCode errorCode = executeRequest(QString("%1v1/account_info"), apiPayload, responseBody, isTestPurchase);
|
||||
@@ -948,8 +1045,7 @@ ErrorCode SubscriptionController::getAccountInfo(const QString &serverId, QJsonO
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
accountInfo = QJsonDocument::fromJson(responseBody).object();
|
||||
|
||||
accountInfo = QJsonDocument::fromJson(responseBody).object();
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
@@ -966,13 +1062,20 @@ QFuture<QPair<ErrorCode, QString>> SubscriptionController::getRenewalLink(const
|
||||
}
|
||||
|
||||
bool isTestPurchase = apiV2->apiConfig.isTestPurchase;
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::userCountryCode, apiV2->apiConfig.userCountryCode)
|
||||
.addField(apiDefs::key::serviceType, apiV2->serviceType())
|
||||
.addField(apiDefs::key::authData, apiV2->authData.toJson())
|
||||
.addField(apiDefs::key::cliVersion, QString(APP_VERSION))
|
||||
.addField(apiDefs::key::subscriptionStatus, getSubscriptionStatusForRenewal(apiV2->apiConfig))
|
||||
.build();
|
||||
QJsonObject authDataJson = apiV2->authData.toJson();
|
||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
||||
QString(APP_VERSION),
|
||||
m_appSettingsRepository->getAppLanguage().name().split("_").first(),
|
||||
m_appSettingsRepository->getInstallationUuid(true),
|
||||
apiV2->apiConfig.userCountryCode,
|
||||
"",
|
||||
apiV2->serviceType(),
|
||||
"",
|
||||
authDataJson };
|
||||
|
||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
||||
apiPayload[apiDefs::key::cliVersion] = QString(APP_VERSION);
|
||||
apiPayload[apiDefs::key::subscriptionStatus] = getSubscriptionStatusForRenewal(apiV2->apiConfig);
|
||||
|
||||
auto gatewayController = QSharedPointer<GatewayController>::create(m_appSettingsRepository->getGatewayEndpoint(isTestPurchase),
|
||||
m_appSettingsRepository->isDevGatewayEnv(isTestPurchase),
|
||||
@@ -1008,14 +1111,21 @@ ErrorCode SubscriptionController::resolveImportServiceCaptcha(const QString &use
|
||||
const QString &captchaSolution,
|
||||
CaptchaInfo *retryCaptchaOut)
|
||||
{
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::userCountryCode, userCountryCode)
|
||||
.addField(apiDefs::key::serviceType, serviceType)
|
||||
.addField(apiDefs::key::serviceProtocol, serviceProtocol)
|
||||
.addField(apiDefs::key::publicKey, publicKeyForProtocol(serviceProtocol, protocolData))
|
||||
.addField(apiDefs::key::captchaId, captchaId)
|
||||
.addField(apiDefs::key::captchaSolution, normalizeCaptchaSolution(captchaSolution))
|
||||
.build();
|
||||
GatewayRequestData gatewayRequestData{QSysInfo::productType(),
|
||||
QString(APP_VERSION),
|
||||
m_appSettingsRepository->getAppLanguage().name().split("_").first(),
|
||||
m_appSettingsRepository->getInstallationUuid(true),
|
||||
userCountryCode,
|
||||
"",
|
||||
serviceType,
|
||||
serviceProtocol,
|
||||
QJsonObject()};
|
||||
|
||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
||||
appendProtocolDataToApiPayload(serviceProtocol, protocolData, apiPayload);
|
||||
|
||||
apiPayload["captcha_id"] = captchaId;
|
||||
apiPayload["captcha_solution"] = normalizeCaptchaSolution(captchaSolution);
|
||||
|
||||
QByteArray responseBody;
|
||||
ErrorCode errorCode = executeRequest(QString("%1v1/config"), apiPayload, responseBody);
|
||||
|
||||
@@ -27,6 +27,21 @@ public:
|
||||
QString xrayUuid;
|
||||
};
|
||||
|
||||
struct GatewayRequestData
|
||||
{
|
||||
QString osVersion;
|
||||
QString appVersion;
|
||||
QString appLanguage;
|
||||
QString installationUuid;
|
||||
QString userCountryCode;
|
||||
QString serverCountryCode;
|
||||
QString serviceType;
|
||||
QString serviceProtocol;
|
||||
QJsonObject authData;
|
||||
|
||||
QJsonObject toJsonObject() const;
|
||||
};
|
||||
|
||||
struct CaptchaInfo {
|
||||
QString captchaId;
|
||||
QString captchaImageBase64;
|
||||
@@ -38,8 +53,7 @@ public:
|
||||
SecureAppSettingsRepository* appSettingsRepository);
|
||||
|
||||
ProtocolData generateProtocolData(const QString &protocol);
|
||||
|
||||
static QString publicKeyForProtocol(const QString &protocol, const ProtocolData &protocolData);
|
||||
void appendProtocolDataToApiPayload(const QString &protocol, const ProtocolData &protocolData, QJsonObject &apiPayload);
|
||||
|
||||
ErrorCode importServiceFromGateway(const QString &userCountryCode, const QString &serviceType,
|
||||
const QString &serviceProtocol, const ProtocolData &protocolData,
|
||||
|
||||
@@ -29,6 +29,7 @@ ConnectionController::ConnectionController(SecureServersRepository* serversRepos
|
||||
m_vpnConnection(vpnConnection)
|
||||
{
|
||||
connect(m_vpnConnection, &VpnConnection::connectionStateChanged, this, &ConnectionController::connectionStateChanged);
|
||||
connect(m_vpnConnection, &VpnConnection::systemWoke, this, &ConnectionController::systemWoke);
|
||||
connect(this, &ConnectionController::openConnectionRequested, m_vpnConnection, &VpnConnection::connectToVpn, Qt::QueuedConnection);
|
||||
connect(this, &ConnectionController::closeConnectionRequested, m_vpnConnection, &VpnConnection::disconnectFromVpn, Qt::QueuedConnection);
|
||||
connect(this, &ConnectionController::killSwitchModeChangedRequested, m_vpnConnection, &VpnConnection::onKillSwitchModeChanged, Qt::QueuedConnection);
|
||||
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
|
||||
signals:
|
||||
void connectionStateChanged(Vpn::ConnectionState state);
|
||||
void systemWoke();
|
||||
void openConnectionRequested(const QString &serverId, DockerContainer container, const QJsonObject &vpnConfiguration);
|
||||
void closeConnectionRequested();
|
||||
void killSwitchModeChangedRequested(bool enabled);
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "core/controllers/coreSignalHandlers.h"
|
||||
#include "logger.h"
|
||||
#include "secureQSettings.h"
|
||||
#include "core/utils/appUiConfig.h"
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
#include "core/utils/installedAppsImageProvider.h"
|
||||
@@ -19,7 +18,7 @@
|
||||
|
||||
#if defined(Q_OS_IOS)
|
||||
#include "platforms/ios/ios_controller.h"
|
||||
#include "core/utils/swiftBridge.h"
|
||||
#include <AmneziaVPN-Swift.h>
|
||||
#endif
|
||||
|
||||
CoreController::CoreController(const QSharedPointer<VpnConnection> &vpnConnection, SecureQSettings* settings,
|
||||
@@ -259,7 +258,7 @@ void CoreController::initAppleController()
|
||||
{
|
||||
#ifdef Q_OS_IOS
|
||||
IosController::Instance()->initialize();
|
||||
QTimer::singleShot(0, this, [this]() { SWIFT_BRIDGE_NAMESPACE::toggleScreenshots(m_appSettingsRepository->isScreenshotsEnabled()); });
|
||||
QTimer::singleShot(0, this, [this]() { AmneziaVPN::toggleScreenshots(m_appSettingsRepository->isScreenshotsEnabled()); });
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -299,15 +298,15 @@ void CoreController::updateTranslator(const QLocale &locale)
|
||||
}
|
||||
|
||||
QStringList availableTranslations;
|
||||
QDirIterator it(":/translations", QStringList(APP_TS_PREFIX "_*.qm"), QDir::Files);
|
||||
QDirIterator it(":/translations", QStringList("amneziavpn_*.qm"), QDir::Files);
|
||||
while (it.hasNext()) {
|
||||
availableTranslations << it.next();
|
||||
}
|
||||
|
||||
// This code allow to load translation for the language only, without country code
|
||||
const QString lang = locale.name().split("_").first();
|
||||
const QString translationFilePrefix = QString(":/translations/" APP_TS_PREFIX "_") + lang;
|
||||
QString strFileName = QString(":/translations/" APP_TS_PREFIX "_%1.qm").arg(locale.name());
|
||||
const QString translationFilePrefix = QString(":/translations/amneziavpn_") + lang;
|
||||
QString strFileName = QString(":/translations/amneziavpn_%1.qm").arg(locale.name());
|
||||
for (const QString &translation : availableTranslations) {
|
||||
if (translation.contains(translationFilePrefix)) {
|
||||
strFileName = translation;
|
||||
@@ -318,7 +317,7 @@ void CoreController::updateTranslator(const QLocale &locale)
|
||||
if (m_translator->load(strFileName)) {
|
||||
QCoreApplication::installTranslator(m_translator);
|
||||
} else {
|
||||
if (m_translator->load(QString(":/translations/" APP_TS_PREFIX "_en.qm"))) {
|
||||
if (m_translator->load(QString(":/translations/amneziavpn_en.qm"))) {
|
||||
QCoreApplication::installTranslator(m_translator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
#include "platforms/ios/ios_controller.h"
|
||||
#include "core/utils/swiftBridge.h"
|
||||
#include <AmneziaVPN-Swift.h>
|
||||
#endif
|
||||
|
||||
CoreSignalHandlers::CoreSignalHandlers(CoreController* coreController, QObject* parent)
|
||||
@@ -413,7 +413,7 @@ void CoreSignalHandlers::initIosImportHandler()
|
||||
void CoreSignalHandlers::initIosSettingsHandler()
|
||||
{
|
||||
#ifdef Q_OS_IOS
|
||||
connect(m_coreController->m_appSettingsRepository, &SecureAppSettingsRepository::screenshotsEnabledChanged, [](bool enabled) { SWIFT_BRIDGE_NAMESPACE::toggleScreenshots(enabled); });
|
||||
connect(m_coreController->m_appSettingsRepository, &SecureAppSettingsRepository::screenshotsEnabledChanged, [](bool enabled) { AmneziaVPN::toggleScreenshots(enabled); });
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -154,13 +154,8 @@ QString IpSplitTunnelingController::normalizeHostname(const QString &hostname) c
|
||||
normalized.replace("https://", "");
|
||||
normalized.replace("http://", "");
|
||||
normalized.replace("ftp://", "");
|
||||
|
||||
if (NetworkUtilities::ipAddressWithSubnetRegExp().exactMatch(normalized)) {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
const QStringList parts = normalized.split("/", Qt::SkipEmptyParts);
|
||||
return parts.isEmpty() ? QString() : parts.first();
|
||||
normalized = normalized.split("/", Qt::SkipEmptyParts).first();
|
||||
return normalized;
|
||||
}
|
||||
|
||||
bool IpSplitTunnelingController::validateHostname(const QString &hostname) const
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "core/models/selfhosted/selfHostedAdminServerConfig.h"
|
||||
#include "core/models/containerConfig.h"
|
||||
#include "core/models/protocolConfig.h"
|
||||
#include "version.h"
|
||||
|
||||
using namespace amnezia;
|
||||
|
||||
@@ -221,10 +220,7 @@ ExportController::ExportResult ExportController::generateWireGuardConfig(const Q
|
||||
result.config.append(line + "\n");
|
||||
}
|
||||
|
||||
const QString qr = qrCodeUtils::generatePlainQrCodeImage(result.config.toUtf8());
|
||||
if (!qr.isEmpty()) {
|
||||
result.qrCodes << qr;
|
||||
}
|
||||
result.qrCodes << generateSingleQrCode(result.config.toUtf8());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -255,10 +251,7 @@ ExportController::ExportResult ExportController::generateAwgConfig(const QString
|
||||
result.config.append(line + "\n");
|
||||
}
|
||||
|
||||
const QString qr = qrCodeUtils::generatePlainQrCodeImage(result.config.toUtf8());
|
||||
if (!qr.isEmpty()) {
|
||||
result.qrCodes << qr;
|
||||
}
|
||||
result.qrCodes << generateSingleQrCode(result.config.toUtf8());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -344,7 +337,7 @@ ExportController::ExportResult ExportController::generateXrayConfig(const QStrin
|
||||
// VlessServerObject doesn't have alpn field, so we embed in serverName if needed
|
||||
}
|
||||
|
||||
result.nativeConfigString = amnezia::serialization::vless::Serialize(vlessServer, APPLICATION_NAME);
|
||||
result.nativeConfigString = amnezia::serialization::vless::Serialize(vlessServer, "AmneziaVPN");
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -376,3 +369,9 @@ QList<QString> ExportController::generateQrCodesFromConfig(const QByteArray &dat
|
||||
{
|
||||
return qrCodeUtils::generateQrCodeImageSeries(data);
|
||||
}
|
||||
|
||||
QString ExportController::generateSingleQrCode(const QByteArray &data)
|
||||
{
|
||||
auto qr = qrCodeUtils::generateQrCode(data);
|
||||
return qrCodeUtils::svgToBase64(QString::fromStdString(toSvgString(qr, 1)));
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ private:
|
||||
|
||||
QString generateVpnUrl(const QByteArray &compressedConfig);
|
||||
QList<QString> generateQrCodesFromConfig(const QByteArray &data);
|
||||
QString generateSingleQrCode(const QByteArray &data);
|
||||
|
||||
SecureServersRepository* m_serversRepository;
|
||||
SecureAppSettingsRepository* m_appSettingsRepository;
|
||||
|
||||
@@ -511,10 +511,9 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data, Config
|
||||
if (trimmedLine.startsWith("[") && trimmedLine.endsWith("]")) {
|
||||
continue;
|
||||
} else {
|
||||
const qsizetype separatorIndex = trimmedLine.indexOf('=');
|
||||
if (separatorIndex > 0) {
|
||||
configMap[trimmedLine.left(separatorIndex).trimmed()] =
|
||||
trimmedLine.mid(separatorIndex + 1).trimmed();
|
||||
QStringList parts = trimmedLine.split(" = ");
|
||||
if (parts.count() == 2) {
|
||||
configMap[parts.at(0).trimmed()] = parts.at(1).trimmed();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -567,9 +566,8 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data, Config
|
||||
lastConfig[configKey::persistentKeepAlive] = configMap.value(protocols::wireguard::PersistentKeepalive);
|
||||
}
|
||||
|
||||
const QStringList allowedIps = configMap.value(protocols::wireguard::AllowedIPs).split(
|
||||
QRegularExpression("\\s*,\\s*"), Qt::SkipEmptyParts);
|
||||
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(allowedIps);
|
||||
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(
|
||||
configMap.value(protocols::wireguard::AllowedIPs).split(", "));
|
||||
|
||||
lastConfig[configKey::allowedIps] = allowedIpsJsonArray;
|
||||
|
||||
@@ -637,24 +635,11 @@ QJsonObject ImportController::extractXrayConfig(const QString &data, ConfigTypes
|
||||
{
|
||||
QJsonParseError parserErr;
|
||||
QJsonDocument jsonConf = QJsonDocument::fromJson(data.toLocal8Bit(), &parserErr);
|
||||
if (parserErr.error != QJsonParseError::NoError || !jsonConf.isObject()) {
|
||||
qDebug() << "Xray config JSON parse failed:" << parserErr.errorString();
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
const QJsonObject parsedConfig = jsonConf.object();
|
||||
if (!parsedConfig.value(protocols::xray::inbounds).isArray()
|
||||
|| !parsedConfig.value(protocols::xray::outbounds).isArray()) {
|
||||
qDebug() << "Xray config is missing inbounds or outbounds";
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
const QString serializedConfig = QString::fromUtf8(jsonConf.toJson());
|
||||
|
||||
QJsonObject xrayVpnConfig;
|
||||
xrayVpnConfig[configKey::config] = serializedConfig;
|
||||
xrayVpnConfig[configKey::config] = jsonConf.toJson().constData();
|
||||
QJsonObject lastConfig;
|
||||
lastConfig[configKey::lastConfig] = serializedConfig;
|
||||
lastConfig[configKey::lastConfig] = jsonConf.toJson().constData();
|
||||
lastConfig[configKey::isThirdPartyConfig] = true;
|
||||
|
||||
QJsonObject containers;
|
||||
|
||||
@@ -201,6 +201,9 @@ ErrorCode InstallController::updateServerConfig(const QString &serverId, DockerC
|
||||
SshSession sshSession;
|
||||
|
||||
bool reinstallRequired = isReinstallContainerRequired(container, oldConfig, newConfig);
|
||||
if (container == DockerContainer::Xray || container == DockerContainer::SSXray) {
|
||||
reinstallRequired = true;
|
||||
}
|
||||
qDebug() << "InstallController::updateServerConfig for container" << container << "reinstall required is" << reinstallRequired;
|
||||
|
||||
ErrorCode errorCode = ErrorCode::NoError;
|
||||
@@ -213,7 +216,7 @@ ErrorCode InstallController::updateServerConfig(const QString &serverId, DockerC
|
||||
awgConfig->serverConfig.protocolVersion = protocols::awg::awgV3;
|
||||
}
|
||||
}
|
||||
} else if (container != DockerContainer::Xray && container != DockerContainer::SSXray) {
|
||||
} else {
|
||||
errorCode = configureContainerWorker(credentials, container, newConfig, sshSession);
|
||||
if (errorCode == ErrorCode::NoError) {
|
||||
errorCode = startupContainerWorker(credentials, container, newConfig, sshSession);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "core/models/serverDescription.h"
|
||||
|
||||
#if defined(Q_OS_IOS) || defined(MACOS_NE)
|
||||
#include "core/utils/swiftBridge.h"
|
||||
#include <AmneziaVPN-Swift.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -351,6 +351,16 @@ void SettingsController::setAppLanguage(const QLocale &locale)
|
||||
m_appSettingsRepository->setAppLanguage(locale);
|
||||
}
|
||||
|
||||
bool SettingsController::isPremV1MigrationReminderActive() const
|
||||
{
|
||||
return m_appSettingsRepository->isPremV1MigrationReminderActive();
|
||||
}
|
||||
|
||||
void SettingsController::disablePremV1MigrationReminder()
|
||||
{
|
||||
m_appSettingsRepository->disablePremV1MigrationReminder();
|
||||
}
|
||||
|
||||
QString SettingsController::nextAvailableServerName() const
|
||||
{
|
||||
return m_serversRepository->nextAvailableServerName();
|
||||
|
||||
@@ -69,6 +69,9 @@ public:
|
||||
|
||||
void enableDevMode();
|
||||
|
||||
bool isPremV1MigrationReminderActive() const;
|
||||
void disablePremV1MigrationReminder();
|
||||
|
||||
QString nextAvailableServerName() const;
|
||||
bool isDevModeEnabled() const;
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
#include <QUrl>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QSysInfo>
|
||||
#include <QTimer>
|
||||
|
||||
#include "amneziaApplication.h"
|
||||
#include "logger.h"
|
||||
#include "version.h"
|
||||
#include "core/controllers/gatewayController.h"
|
||||
#include "core/utils/api/gatewayPayloadBuilder.h"
|
||||
#include "core/utils/constants/apiKeys.h"
|
||||
#include "core/utils/selfhosted/scriptsRegistry.h"
|
||||
|
||||
@@ -98,9 +98,10 @@ void UpdateController::fetchGatewayUrl()
|
||||
m_appSettingsRepository->isStrictKillSwitchEnabled(),
|
||||
m_appSettingsRepository);
|
||||
|
||||
QJsonObject apiPayload = GatewayPayloadBuilder(m_appSettingsRepository)
|
||||
.addField(apiDefs::key::cliVersion, QString(APP_VERSION))
|
||||
.build();
|
||||
QJsonObject apiPayload;
|
||||
apiPayload[apiDefs::key::cliVersion] = QString(APP_VERSION);
|
||||
apiPayload[apiDefs::key::osVersion] = QSysInfo::productType();
|
||||
apiPayload[apiDefs::key::installationUuid] = m_appSettingsRepository->getInstallationUuid(true);
|
||||
|
||||
// Workaround: wait before contacting gateway to avoid rate limit triggered by other requests (news etc.)
|
||||
QTimer::singleShot(1000, this, [this, gatewayController, apiPayload]() {
|
||||
|
||||
@@ -78,8 +78,6 @@ void AwgInstaller::generateAwgParameters(AwgServerConfig &serverConfig)
|
||||
serverConfig.rejectAfterTime = protocols::awg::defaultRejectAfterTime;
|
||||
serverConfig.keepaliveTimeout = protocols::awg::defaultKeepaliveTimeout;
|
||||
serverConfig.maxHandshakeAttempts = protocols::awg::defaultMaxHandshakeAttempts;
|
||||
serverConfig.randomTrailers = protocols::awg::defaultRandomTrailers;
|
||||
serverConfig.disableCookies = protocols::awg::defaultDisableCookies;
|
||||
}
|
||||
|
||||
ErrorCode AwgInstaller::extractConfigFromContainer(DockerContainer container, const ServerCredentials &credentials,
|
||||
@@ -146,8 +144,6 @@ ErrorCode AwgInstaller::extractConfigFromContainer(DockerContainer container, co
|
||||
awgConfig->serverConfig.rejectAfterTime = serverConfigMap.value(configKey::rejectAfterTime);
|
||||
awgConfig->serverConfig.keepaliveTimeout = serverConfigMap.value(configKey::keepaliveTimeout);
|
||||
awgConfig->serverConfig.maxHandshakeAttempts = serverConfigMap.value(configKey::maxHandshakeAttempts);
|
||||
awgConfig->serverConfig.randomTrailers = serverConfigMap.value(configKey::randomTrailers);
|
||||
awgConfig->serverConfig.disableCookies = serverConfigMap.value(configKey::disableCookies);
|
||||
|
||||
awgConfig->serverConfig.protocolVersion = awgConfig->serverProtocolVersion();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace amnezia
|
||||
namespace
|
||||
{
|
||||
template <typename T>
|
||||
bool hasAwg3Markers(const T &config)
|
||||
QString awgVersionOf(const T &config)
|
||||
{
|
||||
auto hasValue = [](const QString &value) { return !value.trimmed().isEmpty(); };
|
||||
|
||||
@@ -29,19 +29,6 @@ namespace
|
||||
config.rejectAfterTime, config.keepaliveTimeout,
|
||||
config.maxHandshakeAttempts };
|
||||
if (std::any_of(awg3Params.begin(), awg3Params.end(), hasValue)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return AwgProtocolConfig::isToggleEnabled(config.randomTrailers)
|
||||
|| AwgProtocolConfig::isToggleEnabled(config.disableCookies);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
QString awgVersionOf(const T &config)
|
||||
{
|
||||
auto hasValue = [](const QString &value) { return !value.trimmed().isEmpty(); };
|
||||
|
||||
if (hasAwg3Markers(config)) {
|
||||
return protocols::awg::awgV3;
|
||||
}
|
||||
|
||||
@@ -147,12 +134,6 @@ QJsonObject AwgServerConfig::toJson() const
|
||||
if (!maxHandshakeAttempts.isEmpty()) {
|
||||
obj[configKey::maxHandshakeAttempts] = maxHandshakeAttempts;
|
||||
}
|
||||
if (!randomTrailers.isEmpty()) {
|
||||
obj[configKey::randomTrailers] = randomTrailers;
|
||||
}
|
||||
if (!disableCookies.isEmpty()) {
|
||||
obj[configKey::disableCookies] = disableCookies;
|
||||
}
|
||||
|
||||
if (isThirdPartyConfig) {
|
||||
obj[configKey::isThirdPartyConfig] = isThirdPartyConfig;
|
||||
@@ -197,8 +178,6 @@ AwgServerConfig AwgServerConfig::fromJson(const QJsonObject& json)
|
||||
config.rejectAfterTime = json.value(configKey::rejectAfterTime).toString();
|
||||
config.keepaliveTimeout = json.value(configKey::keepaliveTimeout).toString();
|
||||
config.maxHandshakeAttempts = json.value(configKey::maxHandshakeAttempts).toString();
|
||||
config.randomTrailers = json.value(configKey::randomTrailers).toString();
|
||||
config.disableCookies = json.value(configKey::disableCookies).toString();
|
||||
|
||||
config.isThirdPartyConfig = json.value(configKey::isThirdPartyConfig).toBool(false);
|
||||
|
||||
@@ -323,12 +302,6 @@ QJsonObject AwgClientConfig::toJson() const
|
||||
if (!maxHandshakeAttempts.isEmpty()) {
|
||||
obj[configKey::maxHandshakeAttempts] = maxHandshakeAttempts;
|
||||
}
|
||||
if (!randomTrailers.isEmpty()) {
|
||||
obj[configKey::randomTrailers] = randomTrailers;
|
||||
}
|
||||
if (!disableCookies.isEmpty()) {
|
||||
obj[configKey::disableCookies] = disableCookies;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
@@ -380,8 +353,6 @@ AwgClientConfig AwgClientConfig::fromJson(const QJsonObject& json)
|
||||
config.rejectAfterTime = json.value(configKey::rejectAfterTime).toString();
|
||||
config.keepaliveTimeout = json.value(configKey::keepaliveTimeout).toString();
|
||||
config.maxHandshakeAttempts = json.value(configKey::maxHandshakeAttempts).toString();
|
||||
config.randomTrailers = json.value(configKey::randomTrailers).toString();
|
||||
config.disableCookies = json.value(configKey::disableCookies).toString();
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -424,16 +395,9 @@ QString AwgProtocolConfig::clientProtocolVersion() const
|
||||
return clientConfig.has_value() ? awgVersionOf(clientConfig.value()) : QString();
|
||||
}
|
||||
|
||||
bool AwgProtocolConfig::isToggleEnabled(const QString &value)
|
||||
{
|
||||
const QString trimmedValue = value.trimmed();
|
||||
return !trimmedValue.isEmpty()
|
||||
&& trimmedValue.compare(QLatin1String(protocols::awg::awgBoolOff), Qt::CaseInsensitive) != 0;
|
||||
}
|
||||
|
||||
QString AwgProtocolConfig::protocolVersionString(const QString &version)
|
||||
{
|
||||
if (version == protocols::awg::awgV3) return QObject::tr(" (version 3.1)");
|
||||
if (version == protocols::awg::awgV3) return QObject::tr(" (version 3)");
|
||||
if (version == protocols::awg::awgV2) return QObject::tr(" (version 2)");
|
||||
if (version == protocols::awg::awgV1_5) return QObject::tr(" (version 1.5)");
|
||||
return "";
|
||||
@@ -473,19 +437,13 @@ bool AwgServerConfig::hasEqualServerSettings(const AwgServerConfig& other) const
|
||||
contentPaddingAddition != other.contentPaddingAddition ||
|
||||
rekeyAfterTime != other.rekeyAfterTime || rekeyTimeout != other.rekeyTimeout ||
|
||||
rejectAfterTime != other.rejectAfterTime || keepaliveTimeout != other.keepaliveTimeout ||
|
||||
maxHandshakeAttempts != other.maxHandshakeAttempts ||
|
||||
randomTrailers != other.randomTrailers || disableCookies != other.disableCookies) {
|
||||
maxHandshakeAttempts != other.maxHandshakeAttempts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AwgServerConfig::hasAwg3Params() const
|
||||
{
|
||||
return hasAwg3Markers(*this);
|
||||
}
|
||||
|
||||
bool AwgProtocolConfig::isHeadersEqual(const QString &h1, const QString &h2, const QString &h3, const QString &h4)
|
||||
{
|
||||
QSet<QString> uniqueHeaders;
|
||||
|
||||
@@ -46,15 +46,12 @@ struct AwgServerConfig {
|
||||
QString rejectAfterTime;
|
||||
QString keepaliveTimeout;
|
||||
QString maxHandshakeAttempts;
|
||||
QString randomTrailers;
|
||||
QString disableCookies;
|
||||
bool isThirdPartyConfig = false;
|
||||
|
||||
QJsonObject toJson() const;
|
||||
static AwgServerConfig fromJson(const QJsonObject& json);
|
||||
|
||||
|
||||
bool hasEqualServerSettings(const AwgServerConfig& other) const;
|
||||
bool hasAwg3Params() const;
|
||||
};
|
||||
|
||||
struct AwgClientConfig {
|
||||
@@ -93,8 +90,6 @@ struct AwgClientConfig {
|
||||
QString rejectAfterTime;
|
||||
QString keepaliveTimeout;
|
||||
QString maxHandshakeAttempts;
|
||||
QString randomTrailers;
|
||||
QString disableCookies;
|
||||
QJsonObject toJson() const;
|
||||
static AwgClientConfig fromJson(const QJsonObject& json);
|
||||
};
|
||||
@@ -109,7 +104,6 @@ struct AwgProtocolConfig {
|
||||
QString serverProtocolVersion() const;
|
||||
QString clientProtocolVersion() const;
|
||||
static QString protocolVersionString(const QString &version);
|
||||
static bool isToggleEnabled(const QString &value);
|
||||
|
||||
bool hasClientConfig() const;
|
||||
void setClientConfig(const AwgClientConfig& config);
|
||||
|
||||
@@ -19,7 +19,6 @@ VpnProtocol::VpnProtocol(const QJsonObject &configuration, QObject *parent)
|
||||
m_connectionState(Vpn::ConnectionState::Unknown),
|
||||
m_rawConfig(configuration),
|
||||
m_timeoutTimer(new QTimer(this)),
|
||||
m_lastError(ErrorCode::NoError),
|
||||
m_receivedBytes(0),
|
||||
m_sentBytes(0)
|
||||
{
|
||||
@@ -36,6 +35,11 @@ void VpnProtocol::setLastError(ErrorCode lastError)
|
||||
qCritical().noquote() << "VpnProtocol error, code" << m_lastError << errorString(m_lastError);
|
||||
}
|
||||
|
||||
void VpnProtocol::recordLastError(ErrorCode lastError)
|
||||
{
|
||||
m_lastError = lastError;
|
||||
}
|
||||
|
||||
ErrorCode VpnProtocol::lastError() const
|
||||
{
|
||||
return m_lastError;
|
||||
|
||||
@@ -89,6 +89,10 @@ protected:
|
||||
void startTimeoutTimer();
|
||||
void stopTimeoutTimer();
|
||||
|
||||
// Remembers the error for lastError() without forcing the Error connection
|
||||
// state, unlike setLastError().
|
||||
void recordLastError(ErrorCode lastError);
|
||||
|
||||
Vpn::ConnectionState m_connectionState;
|
||||
|
||||
QString m_routeGateway;
|
||||
@@ -99,7 +103,7 @@ protected:
|
||||
|
||||
private:
|
||||
QTimer* m_timeoutTimer;
|
||||
ErrorCode m_lastError;
|
||||
ErrorCode m_lastError = ErrorCode::NoError;
|
||||
quint64 m_receivedBytes;
|
||||
quint64 m_sentBytes;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
#include <QProcess>
|
||||
#include <QTcpSocket>
|
||||
@@ -50,19 +51,39 @@ WireguardProtocol::~WireguardProtocol()
|
||||
|
||||
void WireguardProtocol::stop()
|
||||
{
|
||||
if (m_stopped) {
|
||||
return;
|
||||
}
|
||||
m_stopped = true;
|
||||
stopMzImpl();
|
||||
return;
|
||||
}
|
||||
|
||||
ErrorCode WireguardProtocol::startMzImpl()
|
||||
{
|
||||
QString protocolName = m_rawConfig.value("protocol").toString();
|
||||
QJsonObject vpnConfigData = m_rawConfig.value(protocolName + "_config_data").toObject();
|
||||
vpnConfigData[configKey::hostName] = NetworkUtilities::getIPAddress(vpnConfigData.value(configKey::hostName).toString());
|
||||
m_rawConfig.insert(protocolName + "_config_data", vpnConfigData);
|
||||
m_rawConfig[configKey::hostName] = NetworkUtilities::getIPAddress(m_rawConfig[configKey::hostName].toString());
|
||||
const QString protocolName = m_rawConfig.value("protocol").toString();
|
||||
const QString configDataKey = protocolName + "_config_data";
|
||||
QJsonObject vpnConfigData = m_rawConfig.value(configDataKey).toObject();
|
||||
|
||||
m_impl->activate(m_rawConfig);
|
||||
const QString endpointHost = vpnConfigData.value(configKey::hostName).toString();
|
||||
const QString endpointIp = NetworkUtilities::getIPAddress(endpointHost);
|
||||
if (endpointIp.isEmpty()) {
|
||||
qWarning() << "WireguardProtocol: unable to resolve the endpoint host, aborting this attempt";
|
||||
recordLastError(ErrorCode::EndpointResolutionError);
|
||||
return ErrorCode::EndpointResolutionError;
|
||||
}
|
||||
|
||||
// Activate a resolved copy: m_rawConfig must keep the original hostname so
|
||||
// a later attempt (e.g. reconnect after wakeup) re-resolves it from scratch
|
||||
// instead of reusing a stale — or empty — address.
|
||||
QJsonObject rawConfig = m_rawConfig;
|
||||
vpnConfigData[configKey::hostName] = endpointIp;
|
||||
rawConfig.insert(configDataKey, vpnConfigData);
|
||||
if (rawConfig.value(configKey::hostName).toString() == endpointHost) {
|
||||
rawConfig[configKey::hostName] = endpointIp;
|
||||
}
|
||||
|
||||
m_impl->activate(rawConfig);
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
@@ -75,5 +96,6 @@ ErrorCode WireguardProtocol::stopMzImpl()
|
||||
|
||||
ErrorCode WireguardProtocol::start()
|
||||
{
|
||||
m_stopped = false;
|
||||
return startMzImpl();
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ public:
|
||||
private:
|
||||
|
||||
QScopedPointer<ControllerImpl> m_impl;
|
||||
bool m_stopped = false;
|
||||
};
|
||||
|
||||
#endif // WIREGUARDPROTOCOL_H
|
||||
|
||||
@@ -442,6 +442,16 @@ void SecureAppSettingsRepository::disableHomeAdLabel()
|
||||
setValue("Conf/homeAdLabelVisible", false);
|
||||
}
|
||||
|
||||
bool SecureAppSettingsRepository::isPremV1MigrationReminderActive() const
|
||||
{
|
||||
return value("Conf/premV1MigrationReminderActive", true).toBool();
|
||||
}
|
||||
|
||||
void SecureAppSettingsRepository::disablePremV1MigrationReminder()
|
||||
{
|
||||
setValue("Conf/premV1MigrationReminderActive", false);
|
||||
}
|
||||
|
||||
QByteArray SecureAppSettingsRepository::backupAppConfig() const
|
||||
{
|
||||
return m_settings->backupAppConfig();
|
||||
|
||||
@@ -90,6 +90,8 @@ public:
|
||||
|
||||
bool isHomeAdLabelVisible() const;
|
||||
void disableHomeAdLabel();
|
||||
bool isPremV1MigrationReminderActive() const;
|
||||
void disablePremV1MigrationReminder();
|
||||
QByteArray backupAppConfig() const;
|
||||
bool restoreAppConfig(const QByteArray &cfg);
|
||||
void clearSettings();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "apiUtils.h"
|
||||
|
||||
#include "core/repositories/secureAppSettingsRepository.h"
|
||||
#include "core/utils/serverConfigUtils.h"
|
||||
#include "core/utils/constants/configKeys.h"
|
||||
#include <QDateTime>
|
||||
@@ -49,30 +48,6 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
QString apiUtils::getAppLanguageCode(const SecureAppSettingsRepository *appSettingsRepository)
|
||||
{
|
||||
if (appSettingsRepository == nullptr) {
|
||||
return {};
|
||||
}
|
||||
return appSettingsRepository->getAppLanguage().name().split("_").first();
|
||||
}
|
||||
|
||||
QString apiUtils::getDistributionChannel()
|
||||
{
|
||||
#if defined(Q_OS_ANDROID)
|
||||
return {};
|
||||
#elif defined(Q_OS_IOS) || defined(MACOS_NE)
|
||||
return QStringLiteral("appstore");
|
||||
#else
|
||||
return QStringLiteral("github");
|
||||
#endif
|
||||
}
|
||||
|
||||
QString apiUtils::getCountryFlagCode(const QString &serverCountryCode)
|
||||
{
|
||||
return serverCountryCode.section('-', 0, 0).toUpper();
|
||||
}
|
||||
|
||||
bool apiUtils::isSubscriptionExpired(const QString &subscriptionEndDate)
|
||||
{
|
||||
if (subscriptionEndDate.isEmpty()) {
|
||||
@@ -192,6 +167,44 @@ bool apiUtils::isPremiumServer(const QJsonObject &serverConfigObject)
|
||||
return premiumTypes.contains(serverConfigUtils::configTypeFromJson(serverConfigObject));
|
||||
}
|
||||
|
||||
QString apiUtils::getPremiumV1VpnKey(const QJsonObject &serverConfigObject)
|
||||
{
|
||||
if (serverConfigUtils::configTypeFromJson(serverConfigObject) != serverConfigUtils::ConfigType::AmneziaPremiumV1) {
|
||||
return {};
|
||||
}
|
||||
|
||||
QList<QPair<QString, QVariant>> orderedFields;
|
||||
orderedFields.append(qMakePair(configKey::name, serverConfigObject[configKey::name].toString()));
|
||||
orderedFields.append(qMakePair(configKey::description, serverConfigObject[configKey::description].toString()));
|
||||
orderedFields.append(qMakePair(configKey::configVersion, serverConfigObject[configKey::configVersion].toDouble()));
|
||||
orderedFields.append(qMakePair(apiDefs::key::protocol, serverConfigObject[apiDefs::key::protocol].toString()));
|
||||
orderedFields.append(qMakePair(apiDefs::key::apiEndpoint, serverConfigObject[apiDefs::key::apiEndpoint].toString()));
|
||||
orderedFields.append(qMakePair(apiDefs::key::apiKey, serverConfigObject[apiDefs::key::apiKey].toString()));
|
||||
|
||||
QString vpnKeyStr = "{";
|
||||
for (int i = 0; i < orderedFields.size(); ++i) {
|
||||
const auto &pair = orderedFields[i];
|
||||
if (pair.second.typeId() == QMetaType::Type::QString) {
|
||||
vpnKeyStr += "\"" + pair.first + "\": \"" + pair.second.toString() + "\"";
|
||||
} else if (pair.second.typeId() == QMetaType::Type::Double || pair.second.typeId() == QMetaType::Type::Int) {
|
||||
vpnKeyStr += "\"" + pair.first + "\": " + QString::number(pair.second.toDouble(), 'f', 1);
|
||||
}
|
||||
|
||||
if (i < orderedFields.size() - 1) {
|
||||
vpnKeyStr += ", ";
|
||||
}
|
||||
}
|
||||
vpnKeyStr += "}";
|
||||
|
||||
QByteArray vpnKeyCompressed = escapeUnicode(vpnKeyStr).toUtf8();
|
||||
vpnKeyCompressed = qCompress(vpnKeyCompressed, 6);
|
||||
vpnKeyCompressed = vpnKeyCompressed.mid(4);
|
||||
|
||||
QByteArray signedData = AMNEZIA_CONFIG_SIGNATURE + vpnKeyCompressed;
|
||||
|
||||
return QString("vpn://%1").arg(QString(signedData.toBase64(QByteArray::Base64UrlEncoding)));
|
||||
}
|
||||
|
||||
QString apiUtils::getPremiumV2VpnKey(const QJsonObject &serverConfigObject)
|
||||
{
|
||||
auto configType = serverConfigUtils::configTypeFromJson(serverConfigObject);
|
||||
|
||||
@@ -11,18 +11,8 @@
|
||||
#include "core/utils/routeModes.h"
|
||||
#include "core/utils/commonStructs.h"
|
||||
|
||||
class SecureAppSettingsRepository;
|
||||
|
||||
namespace apiUtils
|
||||
{
|
||||
QString getAppLanguageCode(const SecureAppSettingsRepository *appSettingsRepository);
|
||||
QString getDistributionChannel();
|
||||
|
||||
// The gateway may report a country code with a region suffix, e.g. "us-west", while flag
|
||||
// resources are named after the ISO 3166-1 alpha-2 code alone. Returns the part before the dash
|
||||
// in upper case.
|
||||
QString getCountryFlagCode(const QString &serverCountryCode);
|
||||
|
||||
bool isSubscriptionExpired(const QString &subscriptionEndDate);
|
||||
|
||||
bool isSubscriptionExpiringSoon(const QString &subscriptionEndDate, int withinDays = 30);
|
||||
@@ -33,6 +23,7 @@ namespace apiUtils
|
||||
const QNetworkReply::NetworkError &replyError, const int httpStatusCode,
|
||||
const QByteArray &responseBody);
|
||||
|
||||
QString getPremiumV1VpnKey(const QJsonObject &serverConfigObject);
|
||||
QString getPremiumV2VpnKey(const QJsonObject &serverConfigObject);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
#include "gatewayPayloadBuilder.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QSysInfo>
|
||||
|
||||
#include "core/repositories/secureAppSettingsRepository.h"
|
||||
#include "core/utils/api/apiUtils.h"
|
||||
#include "core/utils/constants/apiKeys.h"
|
||||
#include "version.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
bool isEmptyValue(const QJsonValue &value)
|
||||
{
|
||||
switch (value.type()) {
|
||||
case QJsonValue::Null:
|
||||
case QJsonValue::Undefined:
|
||||
return true;
|
||||
case QJsonValue::String:
|
||||
return value.toString().isEmpty();
|
||||
case QJsonValue::Object:
|
||||
return value.toObject().isEmpty();
|
||||
case QJsonValue::Array:
|
||||
return value.toArray().isEmpty();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GatewayPayloadBuilder::GatewayPayloadBuilder(const SecureAppSettingsRepository *appSettingsRepository)
|
||||
{
|
||||
m_payload[apiDefs::key::osVersion] = QSysInfo::productType();
|
||||
m_payload[apiDefs::key::appVersion] = QString(APP_VERSION);
|
||||
m_payload[apiDefs::key::cliName] = QString(APPLICATION_NAME);
|
||||
|
||||
const QString distributionChannel = apiUtils::getDistributionChannel();
|
||||
if (!distributionChannel.isEmpty()) {
|
||||
m_payload[apiDefs::key::distribution] = distributionChannel;
|
||||
}
|
||||
|
||||
if (appSettingsRepository == nullptr) {
|
||||
qWarning() << "SecureAppSettingsRepository is null, skip app language and installation uuid";
|
||||
return;
|
||||
}
|
||||
|
||||
m_payload[apiDefs::key::appLanguage] = apiUtils::getAppLanguageCode(appSettingsRepository);
|
||||
m_payload[apiDefs::key::installationUuid] = appSettingsRepository->getInstallationUuid(true);
|
||||
}
|
||||
|
||||
GatewayPayloadBuilder &GatewayPayloadBuilder::addField(QLatin1String key, const QJsonValue &value)
|
||||
{
|
||||
if (!isEmptyValue(value)) {
|
||||
m_payload[key] = value;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
QJsonObject GatewayPayloadBuilder::build() const
|
||||
{
|
||||
return m_payload;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#ifndef GATEWAYPAYLOADBUILDER_H
|
||||
#define GATEWAYPAYLOADBUILDER_H
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QLatin1String>
|
||||
|
||||
class SecureAppSettingsRepository;
|
||||
|
||||
class GatewayPayloadBuilder
|
||||
{
|
||||
public:
|
||||
explicit GatewayPayloadBuilder(const SecureAppSettingsRepository *appSettingsRepository);
|
||||
|
||||
GatewayPayloadBuilder &addField(QLatin1String key, const QJsonValue &value);
|
||||
QJsonObject build() const;
|
||||
|
||||
private:
|
||||
QJsonObject m_payload;
|
||||
};
|
||||
|
||||
#endif // GATEWAYPAYLOADBUILDER_H
|
||||
@@ -1,15 +0,0 @@
|
||||
#ifndef APP_UI_CONFIG_H
|
||||
#define APP_UI_CONFIG_H
|
||||
|
||||
#define APP_INSTANCE_NAME "@CLIENT_APP_INSTANCE_NAME@"
|
||||
#define APP_QML_ENTRYPOINT "@CLIENT_QML_ENTRYPOINT@"
|
||||
#define APP_QML_IMPORT_PATH "@CLIENT_QML_IMPORT_PATH@"
|
||||
#define APP_QML_PAGES_PREFIX "@CLIENT_QML_PAGES_PREFIX@"
|
||||
#define APP_UI_FONT_RESOURCE "@CLIENT_UI_FONT_RESOURCE@"
|
||||
#define APP_TS_PREFIX "@CLIENT_TS_PREFIX@"
|
||||
#define APP_NOTIFICATION_IDENTIFIER "@CLIENT_NOTIFICATION_IDENTIFIER@"
|
||||
#define APP_IOS_BUNDLE_ID "@CLIENT_IOS_BUNDLE_ID@"
|
||||
#define APP_IOS_STORE_URL_FALLBACK "@CLIENT_IOS_STORE_URL_FALLBACK@"
|
||||
#define APP_ANDROID_PACKAGE "@CLIENT_ANDROID_PACKAGE@"
|
||||
|
||||
#endif
|
||||
@@ -23,7 +23,6 @@ namespace apiDefs
|
||||
constexpr QLatin1String installationUuid("installation_uuid");
|
||||
constexpr QLatin1String uuid("installation_uuid");
|
||||
constexpr QLatin1String osVersion("os_version");
|
||||
constexpr QLatin1String distribution("distribution");
|
||||
constexpr QLatin1String userCountryCode("user_country_code");
|
||||
constexpr QLatin1String serverCountryCode("server_country_code");
|
||||
constexpr QLatin1String serverCountryName("server_country_name");
|
||||
@@ -41,10 +40,6 @@ namespace apiDefs
|
||||
constexpr QLatin1String lastDownloaded("last_downloaded");
|
||||
constexpr QLatin1String sourceType("source_type");
|
||||
constexpr QLatin1String appLanguage("app_language");
|
||||
constexpr QLatin1String locale("locale");
|
||||
|
||||
constexpr QLatin1String captchaId("captcha_id");
|
||||
constexpr QLatin1String captchaSolution("captcha_solution");
|
||||
|
||||
constexpr QLatin1String activeDeviceCount("active_device_count");
|
||||
constexpr QLatin1String maxDeviceCount("max_device_count");
|
||||
@@ -67,6 +62,7 @@ namespace apiDefs
|
||||
|
||||
constexpr QLatin1String id("id");
|
||||
constexpr QLatin1String orderId("order_id");
|
||||
constexpr QLatin1String migrationCode("migration_code");
|
||||
constexpr QLatin1String transactionId("transaction_id");
|
||||
constexpr QLatin1String isTestPurchase("is_test_purchase");
|
||||
constexpr QLatin1String isInAppPurchase("is_in_app_purchase");
|
||||
|
||||
@@ -100,8 +100,6 @@ namespace amnezia
|
||||
constexpr QLatin1String rejectAfterTime("RejectAfterTime");
|
||||
constexpr QLatin1String keepaliveTimeout("KeepaliveTimeout");
|
||||
constexpr QLatin1String maxHandshakeAttempts("MaxHandshakeAttempts");
|
||||
constexpr QLatin1String randomTrailers("RandomTrailers");
|
||||
constexpr QLatin1String disableCookies("DisableCookies");
|
||||
|
||||
inline QStringList awgProtocolKeys()
|
||||
{
|
||||
@@ -127,9 +125,7 @@ namespace amnezia
|
||||
rekeyTimeout,
|
||||
rejectAfterTime,
|
||||
keepaliveTimeout,
|
||||
maxHandshakeAttempts,
|
||||
randomTrailers,
|
||||
disableCookies };
|
||||
maxHandshakeAttempts };
|
||||
}
|
||||
|
||||
constexpr QLatin1String openvpn("openvpn");
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace amnezia
|
||||
|
||||
constexpr char awgV1_5[] = "1.5";
|
||||
constexpr char awgV2[] = "2";
|
||||
constexpr char awgV3[] = "3.1";
|
||||
constexpr char awgV3[] = "3";
|
||||
|
||||
constexpr char defaultContentPaddingAddition[] = "10-100";
|
||||
constexpr char defaultRekeyAfterTime[] = "100-120";
|
||||
@@ -213,10 +213,6 @@ namespace amnezia
|
||||
constexpr char defaultKeepaliveTimeout[] = "5-15";
|
||||
constexpr char defaultMaxHandshakeAttempts[] = "15-20";
|
||||
constexpr char defaultPersistentKeepAlive[] = "25-35";
|
||||
constexpr char defaultRandomTrailers[] = "on";
|
||||
constexpr char defaultDisableCookies[] = "on";
|
||||
constexpr char awgBoolOn[] = "on";
|
||||
constexpr char awgBoolOff[] = "off";
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -112,7 +112,8 @@ QMap<DockerContainer, QString> ContainerUtils::containerDescriptions()
|
||||
QObject::tr("Replace the current DNS server with your own. This will increase your privacy level.") },
|
||||
{ DockerContainer::Sftp,
|
||||
QObject::tr("Create a file vault on your server to securely store and transfer files.") },
|
||||
{ DockerContainer::Socks5Proxy, ("") },
|
||||
{ DockerContainer::Socks5Proxy,
|
||||
QObject::tr("") },
|
||||
{ DockerContainer::MtProxy,
|
||||
QObject::tr("Telegram MTProto proxy server") },
|
||||
{ DockerContainer::Telemt,
|
||||
|
||||
@@ -68,6 +68,7 @@ namespace amnezia
|
||||
OpenVpnUnknownError = 701,
|
||||
OpenVpnTapAdapterError = 702,
|
||||
AddressPoolError = 703,
|
||||
EndpointResolutionError = 704,
|
||||
|
||||
// 3rd party utils errors
|
||||
OpenSslFailed = 800,
|
||||
@@ -97,6 +98,7 @@ namespace amnezia
|
||||
ApiServicesMissingError = 1107,
|
||||
ApiConfigLimitError = 1108,
|
||||
ApiNotFoundError = 1109,
|
||||
ApiMigrationError = 1110,
|
||||
ApiUpdateRequestError = 1111,
|
||||
ApiSubscriptionExpiredError = 1112,
|
||||
ApiPurchaseError = 1113,
|
||||
|
||||
@@ -66,6 +66,7 @@ QString errorString(ErrorCode code) {
|
||||
case (ErrorCode::OpenVpnAdaptersInUseError): errorMessage = QObject::tr("Can't connect: another VPN connection is active"); break;
|
||||
case (ErrorCode::OpenVpnTapAdapterError): errorMessage = QObject::tr("Can't setup OpenVPN TAP network adapter"); break;
|
||||
case (ErrorCode::AddressPoolError): errorMessage = QObject::tr("VPN pool error: no available addresses"); break;
|
||||
case (ErrorCode::EndpointResolutionError): errorMessage = QObject::tr("Failed to resolve the VPN server address"); break;
|
||||
|
||||
case (ErrorCode::ImportInvalidConfigError): errorMessage = QObject::tr("The config does not contain any containers and credentials for connecting to the server"); break;
|
||||
case (ErrorCode::ImportBackupFileUseRestoreInstead): errorMessage = QObject::tr("Backup files cannot be imported here. Use 'Restore from backup' instead."); break;
|
||||
@@ -89,6 +90,7 @@ QString errorString(ErrorCode code) {
|
||||
case (ErrorCode::ApiServicesMissingError): errorMessage = QObject::tr("Missing list of available services"); break;
|
||||
case (ErrorCode::ApiConfigLimitError): errorMessage = QObject::tr("The limit of allowed configurations per subscription has been exceeded"); break;
|
||||
case (ErrorCode::ApiNotFoundError): errorMessage = QObject::tr("Error when retrieving configuration from API"); break;
|
||||
case (ErrorCode::ApiMigrationError): errorMessage = QObject::tr("A migration error has occurred. Please contact our technical support"); break;
|
||||
case (ErrorCode::ApiUpdateRequestError): errorMessage = QObject::tr("Please update the application to use this feature"); break;
|
||||
case (ErrorCode::ApiSubscriptionExpiredError): errorMessage = QObject::tr("Your Amnezia Premium subscription has expired.\n Please check your email for renewal instructions.\n If you haven't received an email, please contact our support."); break;
|
||||
case (ErrorCode::ApiPurchaseError): errorMessage = QObject::tr("Unable to process purchase"); break;
|
||||
|
||||
@@ -53,8 +53,7 @@ QRegularExpression NetworkUtilities::ipAddressRegExp()
|
||||
QRegExp NetworkUtilities::ipAddressWithSubnetRegExp()
|
||||
{
|
||||
return QRegExp("(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}"
|
||||
"(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])"
|
||||
"(\\/(?:[0-9]|[1-2][0-9]|3[0-2])){0,1}");
|
||||
"(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(\\/[0-9]{1,2}){0,1}");
|
||||
}
|
||||
|
||||
QRegExp NetworkUtilities::ipNetwork24RegExp()
|
||||
@@ -79,16 +78,12 @@ QString NetworkUtilities::netMaskFromIpWithSubnet(const QString ip)
|
||||
if (!ip.contains("/"))
|
||||
return "255.255.255.255";
|
||||
|
||||
const QStringList parts = ip.split("/");
|
||||
if (parts.size() < 2)
|
||||
return "255.255.255.255";
|
||||
|
||||
bool ok;
|
||||
int prefix = parts.at(1).toInt(&ok);
|
||||
if (!ok || prefix < 0 || prefix > 32)
|
||||
int prefix = ip.split("/").at(1).toInt(&ok);
|
||||
if (!ok)
|
||||
return "255.255.255.255";
|
||||
|
||||
const quint32 mask = prefix == 0 ? 0 : 0xFFFFFFFFu << (32 - prefix);
|
||||
unsigned long mask = (0xFFFFFFFF << (32 - prefix)) & 0xFFFFFFFF;
|
||||
|
||||
return QString("%1.%2.%3.%4").arg(mask >> 24).arg((mask >> 16) & 0xFF).arg((mask >> 8) & 0xFF).arg(mask & 0xFF);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
#include "qrCodeUtils.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QIODevice>
|
||||
#include <QList>
|
||||
|
||||
@@ -19,7 +16,7 @@ QList<QString> qrCodeUtils::generateQrCodeImageSeries(const QByteArray &data)
|
||||
|
||||
QByteArray ba = chunk.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
|
||||
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(ba.constData(), qrcodegen::QrCode::Ecc::LOW);
|
||||
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(ba, qrcodegen::QrCode::Ecc::LOW);
|
||||
QString svg = QString::fromStdString(toSvgString(qr, 1));
|
||||
chunks.append(svgToBase64(svg));
|
||||
}
|
||||
@@ -29,13 +26,9 @@ QList<QString> qrCodeUtils::generateQrCodeImageSeries(const QByteArray &data)
|
||||
|
||||
QString qrCodeUtils::generatePlainQrCodeImage(const QByteArray &data)
|
||||
{
|
||||
try {
|
||||
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(data.constData(), qrcodegen::QrCode::Ecc::LOW);
|
||||
QString svg = QString::fromStdString(toSvgString(qr, 1));
|
||||
return svgToBase64(svg);
|
||||
} catch (const qrcodegen::data_too_long &) {
|
||||
return {};
|
||||
}
|
||||
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(data, qrcodegen::QrCode::Ecc::LOW);
|
||||
QString svg = QString::fromStdString(toSvgString(qr, 1));
|
||||
return svgToBase64(svg);
|
||||
}
|
||||
|
||||
QString qrCodeUtils::svgToBase64(const QString &image)
|
||||
@@ -45,5 +38,5 @@ QString qrCodeUtils::svgToBase64(const QString &image)
|
||||
|
||||
qrcodegen::QrCode qrCodeUtils::generateQrCode(const QByteArray &data)
|
||||
{
|
||||
return qrcodegen::QrCode::encodeText(data.constData(), qrcodegen::QrCode::Ecc::LOW);
|
||||
return qrcodegen::QrCode::encodeText(data, qrcodegen::QrCode::Ecc::LOW);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#ifndef QRCODEUTILS_H
|
||||
#define QRCODEUTILS_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
#include "qrcodegen.hpp"
|
||||
|
||||
@@ -255,8 +255,9 @@ amnezia::ScriptVars amnezia::genAwgVars(const ContainerConfig &containerConfig)
|
||||
vars.append({ { "$SPECIAL_JUNK_4", config.specialJunk4 } });
|
||||
vars.append({ { "$SPECIAL_JUNK_5", config.specialJunk5 } });
|
||||
|
||||
vars.append({ { "$PERSISTENT_KEEPALIVE", config.hasAwg3Params() ? QString(protocols::awg::defaultPersistentKeepAlive)
|
||||
: QString(protocols::wireguard::defaultPersistentKeepAlive) } });
|
||||
const bool isAwg3 = config.protocolVersion == protocols::awg::awgV3;
|
||||
vars.append({ { "$PERSISTENT_KEEPALIVE", isAwg3 ? QString(protocols::awg::defaultPersistentKeepAlive)
|
||||
: QString(protocols::wireguard::defaultPersistentKeepAlive) } });
|
||||
|
||||
vars.append({ { "$HEADER_PROTECTION_KEY", config.headerProtectionKey } });
|
||||
vars.append({ { "$CONTENT_PADDING_ADDITION", config.contentPaddingAddition } });
|
||||
@@ -265,10 +266,6 @@ amnezia::ScriptVars amnezia::genAwgVars(const ContainerConfig &containerConfig)
|
||||
vars.append({ { "$REJECT_AFTER_TIME", config.rejectAfterTime } });
|
||||
vars.append({ { "$KEEPALIVE_TIMEOUT", config.keepaliveTimeout } });
|
||||
vars.append({ { "$MAX_HANDSHAKE_ATTEMPTS", config.maxHandshakeAttempts } });
|
||||
vars.append({ { "$RANDOM_TRAILERS", AwgProtocolConfig::isToggleEnabled(config.randomTrailers)
|
||||
? config.randomTrailers : QString() } });
|
||||
vars.append({ { "$DISABLE_COOKIES", AwgProtocolConfig::isToggleEnabled(config.disableCookies)
|
||||
? config.disableCookies : QString() } });
|
||||
}
|
||||
|
||||
return vars;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef SWIFTBRIDGE_H
|
||||
#define SWIFTBRIDGE_H
|
||||
|
||||
#if defined(Q_OS_IOS) || defined(MACOS_NE)
|
||||
#include "core/utils/swiftBridgeConfig.h"
|
||||
|
||||
#ifndef SWIFT_BRIDGE_OBJC_HEADER
|
||||
#ifdef AMNEZIA_SWIFT_OBJC_HEADER
|
||||
#define SWIFT_BRIDGE_OBJC_HEADER AMNEZIA_SWIFT_OBJC_HEADER
|
||||
#else
|
||||
#define SWIFT_BRIDGE_OBJC_HEADER "AmneziaVPN-Swift.h"
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SWIFT_BRIDGE_NAMESPACE
|
||||
#ifdef AMNEZIA_SWIFT_NAMESPACE
|
||||
#define SWIFT_BRIDGE_NAMESPACE AMNEZIA_SWIFT_NAMESPACE
|
||||
#else
|
||||
#define SWIFT_BRIDGE_NAMESPACE AmneziaVPN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include SWIFT_BRIDGE_OBJC_HEADER
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,7 +0,0 @@
|
||||
#ifndef SWIFT_BRIDGE_CONFIG_H
|
||||
#define SWIFT_BRIDGE_CONFIG_H
|
||||
|
||||
#define SWIFT_BRIDGE_OBJC_HEADER "@CLIENT_SWIFT_OBJC_HEADER_NAME@"
|
||||
#define SWIFT_BRIDGE_NAMESPACE @CLIENT_SWIFT_MODULE_NAME@
|
||||
|
||||
#endif
|
||||
@@ -464,12 +464,6 @@ bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) {
|
||||
if (const auto maxHandshakeAttempts = obj.value("MaxHandshakeAttempts"); !maxHandshakeAttempts.isUndefined()) {
|
||||
config.m_maxHandshakeAttempts = maxHandshakeAttempts.toString();
|
||||
}
|
||||
if (const auto randomTrailers = obj.value("RandomTrailers"); !randomTrailers.isUndefined()) {
|
||||
config.m_randomTrailers = randomTrailers.toString();
|
||||
}
|
||||
if (const auto disableCookies = obj.value("DisableCookies"); !disableCookies.isUndefined()) {
|
||||
config.m_disableCookies = disableCookies.toString();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -643,7 +637,7 @@ void Daemon::checkHandshake() {
|
||||
pendingHandshakes++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check again if there were connections that haven't completed a handshake.
|
||||
if (pendingHandshakes > 0) {
|
||||
m_handshakeTimer.start(HANDSHAKE_POLL_MSEC);
|
||||
|
||||
@@ -179,12 +179,6 @@ QString InterfaceConfig::toWgConf(const QMap<QString, QString>& extra) const {
|
||||
if (!m_maxHandshakeAttempts.isEmpty()) {
|
||||
out << "MaxHandshakeAttempts = " << m_maxHandshakeAttempts << "\n";
|
||||
}
|
||||
if (!m_randomTrailers.isEmpty()) {
|
||||
out << "RandomTrailers = " << m_randomTrailers << "\n";
|
||||
}
|
||||
if (!m_disableCookies.isEmpty()) {
|
||||
out << "DisableCookies = " << m_disableCookies << "\n";
|
||||
}
|
||||
|
||||
// If any extra config was provided, append it now.
|
||||
for (const QString& key : extra.keys()) {
|
||||
@@ -212,13 +206,3 @@ QString InterfaceConfig::toWgConf(const QMap<QString, QString>& extra) const {
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
QString InterfaceConfig::awgBoolToUapi(const QString& value) {
|
||||
const QString v = value.trimmed().toLower();
|
||||
if (v == QLatin1String("on") || v == QLatin1String("1") ||
|
||||
v == QLatin1String("true") || v == QLatin1String("t") ||
|
||||
v == QLatin1String("yes")) {
|
||||
return QStringLiteral("1");
|
||||
}
|
||||
return QStringLiteral("0");
|
||||
}
|
||||
|
||||
@@ -66,16 +66,10 @@ class InterfaceConfig {
|
||||
QString m_rejectAfterTime;
|
||||
QString m_keepaliveTimeout;
|
||||
QString m_maxHandshakeAttempts;
|
||||
QString m_randomTrailers;
|
||||
QString m_disableCookies;
|
||||
|
||||
QJsonObject toJson() const;
|
||||
QString toWgConf(
|
||||
const QMap<QString, QString>& extra = QMap<QString, QString>()) const;
|
||||
|
||||
// Converts awg-quick on/off (and 0/1/true/false) to UAPI 1/0.
|
||||
// amneziawg-go uses strconv.ParseBool and rejects "on"/"off".
|
||||
static QString awgBoolToUapi(const QString& value);
|
||||
};
|
||||
|
||||
#endif // INTERFACECONFIG_H
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
<false/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>${CLIENT_IOS_LAUNCHSCREEN_NAME}</string>
|
||||
<string>AmneziaVPNLaunchScreen</string>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
@@ -70,11 +70,11 @@
|
||||
<key>UIUserInterfaceStyle</key>
|
||||
<string>Light</string>
|
||||
<key>com.wireguard.ios.app_group_id</key>
|
||||
<string>${BUILD_IOS_GROUP_IDENTIFIER}</string>
|
||||
<string>group.org.amnezia.AmneziaVPN</string>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<true/>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>${CLIENT_APPLICATION_NAME} needs access to the camera for reading QR-codes.</string>
|
||||
<string>Amnezia VPN needs access to the camera for reading QR-codes.</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
@@ -116,11 +116,11 @@
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>${CLIENT_APPLICATION_NAME} config</string>
|
||||
<string>Amnezia VPN config</string>
|
||||
<key>UTTypeIconFiles</key>
|
||||
<array/>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>${BUILD_IOS_APP_IDENTIFIER}.amnezia-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.amnezia-config</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
@@ -143,7 +143,7 @@
|
||||
<key>UTTypeIconFiles</key>
|
||||
<array/>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>${BUILD_IOS_APP_IDENTIFIER}.wireguard-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.wireguard-config</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
@@ -167,7 +167,7 @@
|
||||
<key>UTTypeIconFiles</key>
|
||||
<array/>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>${BUILD_IOS_APP_IDENTIFIER}.openvpn-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.openvpn-config</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
@@ -186,11 +186,11 @@
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>${CLIENT_APPLICATION_NAME} backup file</string>
|
||||
<string>AmneziaVPN backup file</string>
|
||||
<key>UTTypeIconFiles</key>
|
||||
<array/>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>${BUILD_IOS_APP_IDENTIFIER}.backup-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.backup-config</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
@@ -208,15 +208,15 @@
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>${CLIENT_APPLICATION_NAME} config</string>
|
||||
<string>Amnezia VPN config</string>
|
||||
<key>LSHandlerRank</key>
|
||||
<string>Alternate</string>
|
||||
<key>LSItemContentTypes</key>
|
||||
<array>
|
||||
<string>${BUILD_IOS_APP_IDENTIFIER}.amnezia-config</string>
|
||||
<string>${BUILD_IOS_APP_IDENTIFIER}.wireguard-config</string>
|
||||
<string>${BUILD_IOS_APP_IDENTIFIER}.openvpn-config</string>
|
||||
<string>${BUILD_IOS_APP_IDENTIFIER}.backup-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.amnezia-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.wireguard-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.openvpn-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.backup-config</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
|
||||
@@ -2,24 +2,24 @@ enable_language(Swift)
|
||||
|
||||
set(CLIENT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
|
||||
|
||||
add_executable(${CLIENT_IOS_NE_TARGET_NAME})
|
||||
set_target_properties(${CLIENT_IOS_NE_TARGET_NAME} PROPERTIES
|
||||
add_executable(networkextension)
|
||||
set_target_properties(networkextension PROPERTIES
|
||||
XCODE_PRODUCT_TYPE com.apple.product-type.app-extension
|
||||
BUNDLE_EXTENSION appex
|
||||
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in
|
||||
MACOSX_BUNDLE_INFO_STRING "${CLIENT_NETWORK_EXTENSION_NAME}"
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "${CLIENT_NETWORK_EXTENSION_NAME}"
|
||||
MACOSX_BUNDLE_INFO_STRING "AmneziaVPNNetworkExtension"
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "AmneziaVPNNetworkExtension"
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}.network-extension"
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION "${CMAKE_PROJECT_VERSION_TWEAK}"
|
||||
MACOSX_BUNDLE_LONG_VERSION_STRING "${APPLE_PROJECT_VERSION}-${CMAKE_PROJECT_VERSION_TWEAK}"
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "${APPLE_PROJECT_VERSION}"
|
||||
|
||||
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}.network-extension"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS ${CLIENT_IOS_NE_ENTITLEMENTS_PATH}
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS ${CMAKE_CURRENT_SOURCE_DIR}/AmneziaVPNNetworkExtension.entitlements
|
||||
XCODE_ATTRIBUTE_MARKETING_VERSION "${APP_MAJOR_VERSION}"
|
||||
XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION "${CMAKE_PROJECT_VERSION_TWEAK}"
|
||||
XCODE_ATTRIBUTE_PRODUCT_NAME "${CLIENT_NETWORK_EXTENSION_NAME}"
|
||||
XCODE_ATTRIBUTE_PRODUCT_NAME "AmneziaVPNNetworkExtension"
|
||||
|
||||
XCODE_ATTRIBUTE_APPLICATION_EXTENSION_API_ONLY "YES"
|
||||
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2"
|
||||
@@ -30,20 +30,20 @@ set_target_properties(${CLIENT_IOS_NE_TARGET_NAME} PROPERTIES
|
||||
)
|
||||
|
||||
if(DEPLOY)
|
||||
set_target_properties(${CLIENT_IOS_NE_TARGET_NAME} PROPERTIES
|
||||
set_target_properties(networkextension PROPERTIES
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=Debug] "Apple Development"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_STYLE Manual
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "${CLIENT_IOS_NE_PROVISIONING_PROFILE_SPECIFIER}"
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "${CLIENT_IOS_NE_PROVISIONING_PROFILE_SPECIFIER_DEBUG}"
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "distr ios.org.amnezia.AmneziaVPN"
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "dev ios.org.amnezia.AmneziaVPN"
|
||||
)
|
||||
else()
|
||||
set_target_properties(${CLIENT_IOS_NE_TARGET_NAME} PROPERTIES
|
||||
set_target_properties(networkextension PROPERTIES
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_STYLE Automatic
|
||||
)
|
||||
endif()
|
||||
|
||||
set_target_properties(${CLIENT_IOS_NE_TARGET_NAME} PROPERTIES
|
||||
set_target_properties(networkextension PROPERTIES
|
||||
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"
|
||||
@@ -51,8 +51,8 @@ set_target_properties(${CLIENT_IOS_NE_TARGET_NAME} PROPERTIES
|
||||
XCODE_ATTRIBUTE_SWIFT_PRECOMPILE_BRIDGING_HEADER "NO"
|
||||
)
|
||||
|
||||
set_target_properties("${CLIENT_IOS_NE_TARGET_NAME}" PROPERTIES
|
||||
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "${BUILD_VPN_DEVELOPMENT_TEAM}"
|
||||
set_target_properties("networkextension" PROPERTIES
|
||||
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "X7UJ388FXK"
|
||||
)
|
||||
|
||||
find_library(FW_ASSETS_LIBRARY AssetsLibrary)
|
||||
@@ -60,17 +60,17 @@ find_library(FW_MOBILE_CORE MobileCoreServices)
|
||||
find_library(FW_UI_KIT UIKit)
|
||||
find_library(FW_LIBRESOLV libresolv.9.tbd)
|
||||
|
||||
target_link_libraries(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE ${FW_ASSETS_LIBRARY})
|
||||
target_link_libraries(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE ${FW_MOBILE_CORE})
|
||||
target_link_libraries(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE ${FW_UI_KIT})
|
||||
target_link_libraries(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE ${FW_LIBRESOLV})
|
||||
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_link_libraries(networkextension PRIVATE ${FW_LIBRESOLV})
|
||||
|
||||
target_compile_options(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\")
|
||||
target_compile_options(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE -DNETWORK_EXTENSION=1)
|
||||
target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\")
|
||||
target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1)
|
||||
|
||||
set(WG_APPLE_SOURCE_DIR ${CLIENT_ROOT_DIR}/3rd/amneziawg-apple/Sources)
|
||||
|
||||
target_sources(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE
|
||||
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
|
||||
@@ -93,7 +93,6 @@ target_sources(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/HevSocksTunnel.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/NELogController.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/Log.swift
|
||||
${CLIENT_GROUP_IDENTIFIER_SWIFT_FILE}
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+WireGuard.swift
|
||||
@@ -104,16 +103,16 @@ target_sources(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/iosglue.mm
|
||||
)
|
||||
|
||||
target_sources(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE
|
||||
target_sources(networkextension PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/PrivacyInfo.xcprivacy
|
||||
)
|
||||
|
||||
set_property(TARGET ${CLIENT_IOS_NE_TARGET_NAME} APPEND PROPERTY RESOURCE
|
||||
set_property(TARGET networkextension APPEND PROPERTY RESOURCE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/PrivacyInfo.xcprivacy
|
||||
)
|
||||
|
||||
target_include_directories(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE ${CLIENT_ROOT_DIR})
|
||||
target_include_directories(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_include_directories(networkextension PRIVATE ${CLIENT_ROOT_DIR})
|
||||
target_include_directories(networkextension PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
find_package(openvpnadapter REQUIRED)
|
||||
# FIXME(ygurov): https://github.com/conan-io/conan/issues/20034
|
||||
@@ -121,10 +120,10 @@ set_property(TARGET amnezia::openvpnadapter APPEND PROPERTY IMPORTED_CONFIGURATI
|
||||
set_property(TARGET amnezia::openvpnadapter APPEND PROPERTY IMPORTED_CONFIGURATIONS MINSIZEREL)
|
||||
set_property(TARGET amnezia::openvpnadapter APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
|
||||
set_property(TARGET amnezia::openvpnadapter APPEND PROPERTY IMPORTED_CONFIGURATIONS RELWITHDEBINFO)
|
||||
target_link_libraries(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE amnezia::openvpnadapter)
|
||||
target_link_libraries(networkextension PRIVATE amnezia::openvpnadapter)
|
||||
|
||||
find_package(awg-apple REQUIRED)
|
||||
target_link_libraries(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE amnezia::awg-apple)
|
||||
target_link_libraries(networkextension PRIVATE amnezia::awg-apple)
|
||||
|
||||
find_package(hev-socks5-tunnel REQUIRED)
|
||||
# FIXME(ygurov): https://github.com/conan-io/conan/issues/20034
|
||||
@@ -132,4 +131,4 @@ set_property(TARGET heiher::hev-socks5-tunnel APPEND PROPERTY IMPORTED_CONFIGURA
|
||||
set_property(TARGET heiher::hev-socks5-tunnel APPEND PROPERTY IMPORTED_CONFIGURATIONS MINSIZEREL)
|
||||
set_property(TARGET heiher::hev-socks5-tunnel APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
|
||||
set_property(TARGET heiher::hev-socks5-tunnel APPEND PROPERTY IMPORTED_CONFIGURATIONS RELWITHDEBINFO)
|
||||
target_link_libraries(${CLIENT_IOS_NE_TARGET_NAME} PRIVATE heiher::hev-socks5-tunnel)
|
||||
target_link_libraries(networkextension PRIVATE heiher::hev-socks5-tunnel)
|
||||
|
||||
@@ -38,9 +38,9 @@
|
||||
</dict>
|
||||
|
||||
<key>com.wireguard.ios.app_group_id</key>
|
||||
<string>${BUILD_IOS_GROUP_IDENTIFIER}</string>
|
||||
<string>group.${BUILD_IOS_APP_IDENTIFIER}</string>
|
||||
|
||||
<key>com.wireguard.macos.app_group_id</key>
|
||||
<string>${BUILD_VPN_DEVELOPMENT_TEAM}.${BUILD_IOS_GROUP_IDENTIFIER}</string>
|
||||
<string>${BUILD_VPN_DEVELOPMENT_TEAM}.group.${BUILD_OSX_APP_IDENTIFIER}</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -34,9 +34,9 @@
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
<true/>
|
||||
<key>com.wireguard.ios.app_group_id</key>
|
||||
<string>${BUILD_IOS_GROUP_IDENTIFIER}</string>
|
||||
<string>group.org.amnezia.AmneziaVPN</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>${CLIENT_APPLICATION_NAME} needs access to the camera for reading QR-codes.</string>
|
||||
<string>Amnezia VPN needs access to the camera for reading QR-codes.</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
@@ -66,11 +66,11 @@
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>${CLIENT_APPLICATION_NAME} config</string>
|
||||
<string>Amnezia VPN config</string>
|
||||
<key>UTTypeIconFiles</key>
|
||||
<array/>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>${BUILD_OSX_APP_IDENTIFIER}.amnezia-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.amnezia-config</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
@@ -93,7 +93,7 @@
|
||||
<key>UTTypeIconFiles</key>
|
||||
<array/>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>${BUILD_OSX_APP_IDENTIFIER}.wireguard-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.wireguard-config</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
@@ -117,7 +117,7 @@
|
||||
<key>UTTypeIconFiles</key>
|
||||
<array/>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>${BUILD_OSX_APP_IDENTIFIER}.openvpn-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.openvpn-config</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
@@ -136,11 +136,11 @@
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>${CLIENT_APPLICATION_NAME} backup file</string>
|
||||
<string>AmneziaVPN backup file</string>
|
||||
<key>UTTypeIconFiles</key>
|
||||
<array/>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>${BUILD_OSX_APP_IDENTIFIER}.backup-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.backup-config</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
@@ -158,15 +158,15 @@
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>${CLIENT_APPLICATION_NAME} config</string>
|
||||
<string>Amnezia VPN config</string>
|
||||
<key>LSHandlerRank</key>
|
||||
<string>Alternate</string>
|
||||
<key>LSItemContentTypes</key>
|
||||
<array>
|
||||
<string>${BUILD_OSX_APP_IDENTIFIER}.amnezia-config</string>
|
||||
<string>${BUILD_OSX_APP_IDENTIFIER}.wireguard-config</string>
|
||||
<string>${BUILD_OSX_APP_IDENTIFIER}.openvpn-config</string>
|
||||
<string>${BUILD_OSX_APP_IDENTIFIER}.backup-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.amnezia-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.wireguard-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.openvpn-config</string>
|
||||
<string>org.amnezia.AmneziaVPN.backup-config</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
@@ -180,6 +180,5 @@
|
||||
</dict>
|
||||
</array>
|
||||
|
||||
${CLIENT_MACOS_EXTRA_PLIST_ENTRIES}
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1,27 +1,22 @@
|
||||
enable_language(Swift)
|
||||
message("Client message >> macos build >> ${CLIENT_MACOS_NE_TARGET_NAME}")
|
||||
message("Client message >> macos build >> AmneziaVPNNetworkExtension")
|
||||
set(CLIENT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
|
||||
|
||||
add_executable(${CLIENT_MACOS_NE_TARGET_NAME})
|
||||
add_executable(AmneziaVPNNetworkExtension)
|
||||
|
||||
message("executable_path is: @executable_path/../../Frameworks")
|
||||
|
||||
# The plist is consumed by Xcode directly, so branding variables have to be
|
||||
# substituted by CMake beforehand
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in ${CMAKE_CURRENT_BINARY_DIR}/Info.plist)
|
||||
|
||||
set_target_properties(${CLIENT_MACOS_NE_TARGET_NAME} PROPERTIES
|
||||
set_target_properties(AmneziaVPNNetworkExtension PROPERTIES
|
||||
XCODE_PRODUCT_TYPE com.apple.product-type.app-extension
|
||||
BUNDLE_EXTENSION appex
|
||||
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}.network-extension"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS ${CLIENT_MACOS_NE_ENTITLEMENTS_PATH}
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS ${CMAKE_CURRENT_SOURCE_DIR}/AmneziaVPNNetworkExtension.entitlements
|
||||
XCODE_ATTRIBUTE_MARKETING_VERSION "${APP_MAJOR_VERSION}"
|
||||
XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION "${CMAKE_PROJECT_VERSION_TWEAK}"
|
||||
XCODE_ATTRIBUTE_PRODUCT_NAME "${CLIENT_NETWORK_EXTENSION_NAME}"
|
||||
XCODE_ATTRIBUTE_PRODUCT_NAME "AmneziaVPNNetworkExtension"
|
||||
|
||||
XCODE_ATTRIBUTE_APPLICATION_EXTENSION_API_ONLY "YES"
|
||||
|
||||
XCODE_ATTRIBUTE_INFOPLIST_FILE ${CMAKE_CURRENT_BINARY_DIR}/Info.plist
|
||||
XCODE_ATTRIBUTE_INFOPLIST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in
|
||||
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../../../../Frameworks @loader_path/../../../../Frameworks"
|
||||
|
||||
XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION
|
||||
@@ -29,20 +24,20 @@ set_target_properties(${CLIENT_MACOS_NE_TARGET_NAME} PROPERTIES
|
||||
|
||||
if(DEPLOY)
|
||||
message("DEPLOY is ON")
|
||||
set_target_properties(${CLIENT_MACOS_NE_TARGET_NAME} PROPERTIES
|
||||
set_target_properties(AmneziaVPNNetworkExtension PROPERTIES
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=Debug] "Apple Development"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_STYLE Manual
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "${CLIENT_MACOS_NE_PROVISIONING_PROFILE_SPECIFIER}"
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "${CLIENT_MACOS_NE_PROVISIONING_PROFILE_SPECIFIER_DEBUG}"
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "distr macos.org.amnezia.amneziaVPN.NE"
|
||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "dev macos.org.amnezia.amneziaVPN.NE"
|
||||
)
|
||||
else()
|
||||
set_target_properties(${CLIENT_MACOS_NE_TARGET_NAME} PROPERTIES
|
||||
set_target_properties(AmneziaVPNNetworkExtension PROPERTIES
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_STYLE Automatic
|
||||
)
|
||||
endif()
|
||||
|
||||
set_target_properties(${CLIENT_MACOS_NE_TARGET_NAME} PROPERTIES
|
||||
set_target_properties(AmneziaVPNNetworkExtension PROPERTIES
|
||||
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"
|
||||
@@ -50,8 +45,8 @@ set_target_properties(${CLIENT_MACOS_NE_TARGET_NAME} PROPERTIES
|
||||
XCODE_ATTRIBUTE_SWIFT_PRECOMPILE_BRIDGING_HEADER "NO"
|
||||
)
|
||||
|
||||
set_target_properties("${CLIENT_MACOS_NE_TARGET_NAME}" PROPERTIES
|
||||
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "${BUILD_VPN_DEVELOPMENT_TEAM}"
|
||||
set_target_properties("AmneziaVPNNetworkExtension" PROPERTIES
|
||||
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "X7UJ388FXK"
|
||||
)
|
||||
|
||||
find_library(FW_ASSETS_LIBRARY AssetsLibrary)
|
||||
@@ -63,17 +58,17 @@ find_library(FW_LIBRESOLV libresolv.9.tbd)
|
||||
# Set the root directory
|
||||
set(CLIENT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
|
||||
|
||||
target_link_libraries(${CLIENT_MACOS_NE_TARGET_NAME} PRIVATE ${FW_LIBRESOLV})
|
||||
target_link_libraries(AmneziaVPNNetworkExtension PRIVATE ${FW_LIBRESOLV})
|
||||
|
||||
target_compile_options(${CLIENT_MACOS_NE_TARGET_NAME} PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\")
|
||||
target_compile_options(${CLIENT_MACOS_NE_TARGET_NAME} PRIVATE -DNETWORK_EXTENSION=1)
|
||||
target_compile_options(AmneziaVPNNetworkExtension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\")
|
||||
target_compile_options(AmneziaVPNNetworkExtension PRIVATE -DNETWORK_EXTENSION=1)
|
||||
|
||||
set(WG_APPLE_SOURCE_DIR ${CLIENT_ROOT_DIR}/3rd/amneziawg-apple/Sources)
|
||||
|
||||
message("WG_APPLE_SOURCE_DIR is: ${WG_APPLE_SOURCE_DIR}")
|
||||
message("CLIENT_ROOT_DIR is: ${CLIENT_ROOT_DIR}")
|
||||
|
||||
target_sources(${CLIENT_MACOS_NE_TARGET_NAME} PRIVATE
|
||||
target_sources(AmneziaVPNNetworkExtension PRIVATE
|
||||
${WG_APPLE_SOURCE_DIR}/WireGuardKit/WireGuardAdapter.swift
|
||||
${WG_APPLE_SOURCE_DIR}/WireGuardKit/PacketTunnelSettingsGenerator.swift
|
||||
${WG_APPLE_SOURCE_DIR}/WireGuardKit/DNSResolver.swift
|
||||
@@ -96,7 +91,6 @@ target_sources(${CLIENT_MACOS_NE_TARGET_NAME} PRIVATE
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/HevSocksTunnel.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/NELogController.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/Log.swift
|
||||
${CLIENT_GROUP_IDENTIFIER_SWIFT_FILE}
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+WireGuard.swift
|
||||
@@ -107,16 +101,16 @@ target_sources(${CLIENT_MACOS_NE_TARGET_NAME} PRIVATE
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/XrayConfig.swift
|
||||
)
|
||||
|
||||
target_sources(${CLIENT_MACOS_NE_TARGET_NAME} PRIVATE
|
||||
target_sources(AmneziaVPNNetworkExtension PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/PrivacyInfo.xcprivacy
|
||||
)
|
||||
|
||||
set_property(TARGET ${CLIENT_MACOS_NE_TARGET_NAME} APPEND PROPERTY RESOURCE
|
||||
set_property(TARGET AmneziaVPNNetworkExtension APPEND PROPERTY RESOURCE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/PrivacyInfo.xcprivacy
|
||||
)
|
||||
|
||||
target_include_directories(${CLIENT_MACOS_NE_TARGET_NAME} PRIVATE ${CLIENT_ROOT_DIR})
|
||||
target_include_directories(${CLIENT_MACOS_NE_TARGET_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_include_directories(AmneziaVPNNetworkExtension PRIVATE ${CLIENT_ROOT_DIR})
|
||||
target_include_directories(AmneziaVPNNetworkExtension PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
find_package(openvpnadapter REQUIRED)
|
||||
# FIXME(ygurov): https://github.com/conan-io/conan/issues/20034
|
||||
@@ -124,10 +118,10 @@ set_property(TARGET amnezia::openvpnadapter APPEND PROPERTY IMPORTED_CONFIGURATI
|
||||
set_property(TARGET amnezia::openvpnadapter APPEND PROPERTY IMPORTED_CONFIGURATIONS MINSIZEREL)
|
||||
set_property(TARGET amnezia::openvpnadapter APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
|
||||
set_property(TARGET amnezia::openvpnadapter APPEND PROPERTY IMPORTED_CONFIGURATIONS RELWITHDEBINFO)
|
||||
target_link_libraries(${CLIENT_MACOS_NE_TARGET_NAME} PRIVATE amnezia::openvpnadapter)
|
||||
target_link_libraries(AmneziaVPNNetworkExtension PRIVATE amnezia::openvpnadapter)
|
||||
|
||||
find_package(awg-apple REQUIRED)
|
||||
target_link_libraries(${CLIENT_MACOS_NE_TARGET_NAME} PRIVATE amnezia::awg-apple)
|
||||
target_link_libraries(AmneziaVPNNetworkExtension PRIVATE amnezia::awg-apple)
|
||||
|
||||
find_package(hev-socks5-tunnel REQUIRED)
|
||||
# FIXME(ygurov): https://github.com/conan-io/conan/issues/20034
|
||||
@@ -135,4 +129,4 @@ set_property(TARGET heiher::hev-socks5-tunnel APPEND PROPERTY IMPORTED_CONFIGURA
|
||||
set_property(TARGET heiher::hev-socks5-tunnel APPEND PROPERTY IMPORTED_CONFIGURATIONS MINSIZEREL)
|
||||
set_property(TARGET heiher::hev-socks5-tunnel APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
|
||||
set_property(TARGET heiher::hev-socks5-tunnel APPEND PROPERTY IMPORTED_CONFIGURATIONS RELWITHDEBINFO)
|
||||
target_link_libraries(${CLIENT_MACOS_NE_TARGET_NAME} PRIVATE heiher::hev-socks5-tunnel)
|
||||
target_link_libraries(AmneziaVPNNetworkExtension PRIVATE heiher::hev-socks5-tunnel)
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${CLIENT_NETWORK_EXTENSION_NAME}</string>
|
||||
<string>AmneziaVPNNetworkExtension</string>
|
||||
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${CLIENT_NETWORK_EXTENSION_NAME}</string>
|
||||
<string>AmneziaVPNNetworkExtension</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
@@ -27,7 +27,7 @@
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>${CLIENT_NETWORK_EXTENSION_NAME}</string>
|
||||
<string>AmneziaVPNNetworkExtension</string>
|
||||
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
@@ -38,9 +38,9 @@
|
||||
</dict>
|
||||
|
||||
<key>com.wireguard.ios.app_group_id</key>
|
||||
<string>${BUILD_IOS_GROUP_IDENTIFIER}</string>
|
||||
<string>group.org.amnezia.AmneziaVPN</string>
|
||||
|
||||
<key>com.wireguard.macos.app_group_id</key>
|
||||
<string>$(DEVELOPMENT_TEAM).${BUILD_IOS_GROUP_IDENTIFIER}</string>
|
||||
<string>$(DEVELOPMENT_TEAM).group.org.amnezia.AmneziaVPN</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "amneziaApplication.h"
|
||||
#include "core/utils/osSignalHandler.h"
|
||||
#include "core/utils/migrations.h"
|
||||
#include "core/utils/appUiConfig.h"
|
||||
#include "version.h"
|
||||
|
||||
|
||||
@@ -27,9 +26,9 @@ void anchorOpenSSL() {
|
||||
bool isAnotherInstanceRunning()
|
||||
{
|
||||
QLocalSocket socket;
|
||||
socket.connectToServer(APP_INSTANCE_NAME);
|
||||
socket.connectToServer("AmneziaVPNInstance");
|
||||
if (socket.waitForConnected(500)) {
|
||||
qWarning() << APPLICATION_NAME << "is already running";
|
||||
qWarning() << "AmneziaVPN is already running";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -76,7 +76,16 @@ void LocalSocketController::errorOccurred(
|
||||
}
|
||||
|
||||
qCritical() << "ControllerError";
|
||||
disconnectInternal();
|
||||
|
||||
// The socket to the daemon is gone (daemon restart/crash or a failed
|
||||
// connection attempt). Unlike a plain tunnel-down message we cannot talk to
|
||||
// the daemon anymore, so remember that and let the next activate()/
|
||||
// deactivate() re-establish the connection instead of writing into a dead
|
||||
// socket forever.
|
||||
m_daemonState = eDisconnected;
|
||||
m_initializingRetry = 0;
|
||||
m_initializingTimer.stop();
|
||||
emit disconnected();
|
||||
}
|
||||
|
||||
void LocalSocketController::disconnectInternal() {
|
||||
@@ -122,7 +131,38 @@ void LocalSocketController::daemonConnected() {
|
||||
checkStatus();
|
||||
}
|
||||
|
||||
bool LocalSocketController::isSocketAlive() const {
|
||||
// ConnectingState counts as alive: on a fresh protocol activate() runs
|
||||
// right after initialize(), before the connection (and the status
|
||||
// handshake) completes — writes are buffered by the socket, and the daemon
|
||||
// processes them once the connection is established.
|
||||
const QLocalSocket::LocalSocketState state = m_socket->state();
|
||||
return state == QLocalSocket::ConnectedState ||
|
||||
state == QLocalSocket::ConnectingState;
|
||||
}
|
||||
|
||||
void LocalSocketController::reconnectToDaemon() {
|
||||
if (m_daemonState == eInitializing) {
|
||||
// A connection attempt is already in progress.
|
||||
return;
|
||||
}
|
||||
if (isSocketAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.warning() << "Daemon socket is not connected; reconnecting";
|
||||
m_initializingRetry = 0;
|
||||
initializeInternal();
|
||||
}
|
||||
|
||||
void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
||||
if (!isSocketAlive()) {
|
||||
logger.error() << "Cannot activate, daemon connection is not ready";
|
||||
reconnectToDaemon();
|
||||
emit disconnected();
|
||||
return;
|
||||
}
|
||||
|
||||
QString protocolName = rawConfig.value("protocol").toString();
|
||||
|
||||
int splitTunnelType = rawConfig.value("splitTunnelType").toInt();
|
||||
@@ -267,8 +307,9 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
||||
void LocalSocketController::deactivate() {
|
||||
logger.debug() << "Deactivating";
|
||||
|
||||
if (m_daemonState != eReady) {
|
||||
if (m_daemonState != eReady || !isSocketAlive()) {
|
||||
logger.debug() << "No disconnect, controller is not ready";
|
||||
reconnectToDaemon();
|
||||
emit disconnected();
|
||||
return;
|
||||
}
|
||||
@@ -334,7 +375,12 @@ void LocalSocketController::readData() {
|
||||
logger.debug() << "Reading";
|
||||
|
||||
Q_ASSERT(m_socket);
|
||||
Q_ASSERT(m_daemonState == eInitializing || m_daemonState == eReady);
|
||||
if (m_daemonState != eInitializing && m_daemonState != eReady) {
|
||||
// Stray data delivered around a socket teardown — nothing to do with it.
|
||||
m_socket->readAll();
|
||||
m_buffer.clear();
|
||||
return;
|
||||
}
|
||||
QByteArray input = m_socket->readAll();
|
||||
m_buffer.append(input);
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ class LocalSocketController final : public ControllerImpl {
|
||||
private:
|
||||
void initializeInternal();
|
||||
void disconnectInternal();
|
||||
void reconnectToDaemon();
|
||||
bool isSocketAlive() const;
|
||||
|
||||
void daemonConnected();
|
||||
void errorOccurred(QLocalSocket::LocalSocketError socketError);
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
enum BuildConfig {
|
||||
static let appGroupIdentifier = "@BUILD_IOS_GROUP_IDENTIFIER@"
|
||||
}
|
||||
@@ -15,7 +15,7 @@ struct Log {
|
||||
}
|
||||
}
|
||||
|
||||
private static let appGroupID = BuildConfig.appGroupIdentifier
|
||||
private static let appGroupID = "group.org.amnezia.AmneziaVPN"
|
||||
|
||||
static let appLogURL = {
|
||||
let sharedContainerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupID)!
|
||||
|
||||
@@ -92,7 +92,7 @@ extension PacketTunnelProvider {
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
wg_log(.error, message: "Can't parse WG config: \(String(describing: error))")
|
||||
wg_log(.error, message: "Can't parse WG config: \(error.localizedDescription)")
|
||||
errorNotifier.notify(PacketTunnelProviderError.savedProtocolConfigurationIsInvalid)
|
||||
completionHandler(PacketTunnelProviderError.savedProtocolConfigurationIsInvalid)
|
||||
return
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
|
||||
#import "StoreKitController.h"
|
||||
#import <StoreKit/StoreKit.h>
|
||||
#include <QtCore/qglobal.h>
|
||||
#import "core/utils/swiftBridge.h"
|
||||
#import <AmneziaVPN-Swift.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QString>
|
||||
|
||||
@@ -8,7 +8,6 @@ struct WGConfig: Decodable {
|
||||
let specialJunk1, specialJunk2, specialJunk3, specialJunk4, specialJunk5: String?
|
||||
let headerProtectionKey: String?
|
||||
let contentPaddingAddition, rekeyAfterTime, rekeyTimeout, rejectAfterTime, keepaliveTimeout, maxHandshakeAttempts: String?
|
||||
let randomTrailers, disableCookies: String?
|
||||
let dns1: String
|
||||
let dns2: String
|
||||
let mtu: String
|
||||
@@ -34,7 +33,6 @@ struct WGConfig: Decodable {
|
||||
case rekeyAfterTime = "RekeyAfterTime", rekeyTimeout = "RekeyTimeout"
|
||||
case rejectAfterTime = "RejectAfterTime", keepaliveTimeout = "KeepaliveTimeout"
|
||||
case maxHandshakeAttempts = "MaxHandshakeAttempts"
|
||||
case randomTrailers = "RandomTrailers", disableCookies = "DisableCookies"
|
||||
case dns1
|
||||
case dns2
|
||||
case mtu
|
||||
@@ -130,12 +128,6 @@ struct WGConfig: Decodable {
|
||||
if let maxHandshakeAttempts = trimmed(maxHandshakeAttempts) {
|
||||
settingsLines.append("MaxHandshakeAttempts = \(maxHandshakeAttempts)")
|
||||
}
|
||||
if let randomTrailers = trimmed(randomTrailers) {
|
||||
settingsLines.append("RandomTrailers = \(randomTrailers)")
|
||||
}
|
||||
if let disableCookies = trimmed(disableCookies) {
|
||||
settingsLines.append("DisableCookies = \(disableCookies)")
|
||||
}
|
||||
|
||||
return settingsLines.joined(separator: "\n")
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#include "platforms/ios/iosnotificationhandler.h"
|
||||
|
||||
#include "core/utils/appUiConfig.h"
|
||||
|
||||
#import <UserNotifications/UserNotifications.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@@ -77,8 +75,7 @@ void IOSNotificationHandler::notify(NotificationHandler::Message type, const QSt
|
||||
UNTimeIntervalNotificationTrigger* trigger =
|
||||
[UNTimeIntervalNotificationTrigger triggerWithTimeInterval:timerSec repeats:NO];
|
||||
|
||||
UNNotificationRequest* request =
|
||||
[UNNotificationRequest requestWithIdentifier:[NSString stringWithUTF8String:APP_NOTIFICATION_IDENTIFIER]
|
||||
UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:@"amneziavpn"
|
||||
content:content
|
||||
trigger:trigger];
|
||||
|
||||
@@ -160,8 +157,7 @@ void IOSNotificationHandler::notify(NotificationHandler::Message type, const QSt
|
||||
UNTimeIntervalNotificationTrigger* trigger =
|
||||
[UNTimeIntervalNotificationTrigger triggerWithTimeInterval:timerSec repeats:NO];
|
||||
|
||||
UNNotificationRequest* request =
|
||||
[UNNotificationRequest requestWithIdentifier:[NSString stringWithUTF8String:APP_NOTIFICATION_IDENTIFIER]
|
||||
UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:@"amneziavpn"
|
||||
content:content
|
||||
trigger:trigger];
|
||||
|
||||
|
||||
@@ -7,10 +7,14 @@
|
||||
#include <net/if.h>
|
||||
|
||||
#include <QDBusVariant>
|
||||
#include <QNetworkInterface>
|
||||
#include <QTimer>
|
||||
#include <QtDBus/QtDBus>
|
||||
|
||||
#include "core/utils/networkUtilities.h"
|
||||
#include "leakdetector.h"
|
||||
#include "logger.h"
|
||||
#include "router_linux.h"
|
||||
|
||||
constexpr const char* DBUS_RESOLVE_SERVICE = "org.freedesktop.resolve1";
|
||||
constexpr const char* DBUS_RESOLVE_PATH = "/org/freedesktop/resolve1";
|
||||
@@ -27,24 +31,56 @@ DnsUtilsLinux::DnsUtilsLinux(QObject* parent) : DnsUtils(parent) {
|
||||
logger.debug() << "DnsUtilsLinux created.";
|
||||
|
||||
QDBusConnection conn = QDBusConnection::systemBus();
|
||||
m_resolver = new QDBusInterface(DBUS_RESOLVE_SERVICE, DBUS_RESOLVE_PATH,
|
||||
DBUS_RESOLVE_MANAGER, conn, this);
|
||||
auto* watcher = new QDBusServiceWatcher(
|
||||
DBUS_RESOLVE_SERVICE, conn,
|
||||
QDBusServiceWatcher::WatchForRegistration |
|
||||
QDBusServiceWatcher::WatchForUnregistration, this);
|
||||
|
||||
connect(watcher, &QDBusServiceWatcher::serviceRegistered,
|
||||
this, &DnsUtilsLinux::onResolverRegistered);
|
||||
connect(watcher, &QDBusServiceWatcher::serviceUnregistered,
|
||||
this, &DnsUtilsLinux::onResolverUnregistered);
|
||||
|
||||
if (conn.interface()->isServiceRegistered(DBUS_RESOLVE_SERVICE)) {
|
||||
onResolverRegistered();
|
||||
}
|
||||
}
|
||||
|
||||
void DnsUtilsLinux::onResolverRegistered() {
|
||||
m_resolver.reset(new QDBusInterface(DBUS_RESOLVE_SERVICE, DBUS_RESOLVE_PATH,
|
||||
DBUS_RESOLVE_MANAGER,
|
||||
QDBusConnection::systemBus()));
|
||||
logger.debug() << "systemd-resolved available, DNS resolver initialized";
|
||||
|
||||
if (!m_pendingIfname.isEmpty()) {
|
||||
logger.debug() << "Re-applying DNS configuration for" << m_pendingIfname;
|
||||
updateResolvers(m_pendingIfname, m_pendingResolvers);
|
||||
}
|
||||
}
|
||||
|
||||
void DnsUtilsLinux::onResolverUnregistered() {
|
||||
logger.debug() << "systemd-resolved disappeared, dropping DNS resolver";
|
||||
m_resolver.reset();
|
||||
}
|
||||
|
||||
DnsUtilsLinux::~DnsUtilsLinux() {
|
||||
MZ_COUNT_DTOR(DnsUtilsLinux);
|
||||
|
||||
for (auto iterator = m_linkDomains.constBegin();
|
||||
iterator != m_linkDomains.constEnd(); ++iterator) {
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(iterator.key());
|
||||
argumentList << QVariant::fromValue(iterator.value());
|
||||
m_resolver->asyncCallWithArgumentList(QStringLiteral("SetLinkDomains"),
|
||||
argumentList);
|
||||
}
|
||||
if (m_resolver) {
|
||||
if (m_gatewayIfindex > 0)
|
||||
setLinkDefaultRoute(m_gatewayIfindex, true);
|
||||
|
||||
if (m_ifindex > 0) {
|
||||
m_resolver->asyncCall(QStringLiteral("RevertLink"), m_ifindex);
|
||||
for (auto iterator = m_linkDomains.constBegin();
|
||||
iterator != m_linkDomains.constEnd(); ++iterator) {
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(iterator.key());
|
||||
argumentList << QVariant::fromValue(iterator.value());
|
||||
m_resolver->asyncCallWithArgumentList(QStringLiteral("SetLinkDomains"),
|
||||
argumentList);
|
||||
}
|
||||
if (m_ifindex > 0) {
|
||||
m_resolver->asyncCall(QStringLiteral("RevertLink"), m_ifindex);
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug() << "DnsUtilsLinux destroyed.";
|
||||
@@ -52,19 +88,52 @@ DnsUtilsLinux::~DnsUtilsLinux() {
|
||||
|
||||
bool DnsUtilsLinux::updateResolvers(const QString& ifname,
|
||||
const QList<QHostAddress>& resolvers) {
|
||||
if (m_gatewayIfindex > 0) {
|
||||
setLinkDefaultRoute(m_gatewayIfindex, true);
|
||||
m_gatewayIfindex = 0;
|
||||
}
|
||||
|
||||
const int previousIfindex = m_ifindex;
|
||||
m_ifindex = if_nametoindex(qPrintable(ifname));
|
||||
if (m_ifindex <= 0) {
|
||||
logger.error() << "Unable to resolve ifindex for" << ifname;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pendingIfname = ifname;
|
||||
m_pendingResolvers = resolvers;
|
||||
|
||||
if (!m_resolver) {
|
||||
logger.debug() << "systemd-resolved not ready, queuing DNS configuration";
|
||||
return true;
|
||||
}
|
||||
|
||||
const int gwIdx = NetworkUtilities::getGatewayAndIface().second.index();
|
||||
if (gwIdx > 0 && gwIdx != m_ifindex && gwIdx != m_gatewayIfindex) {
|
||||
m_gatewayIfindex = gwIdx;
|
||||
setLinkDefaultRoute(gwIdx, false);
|
||||
}
|
||||
|
||||
setLinkDNS(m_ifindex, resolvers);
|
||||
setLinkDefaultRoute(m_ifindex, true);
|
||||
updateLinkDomains();
|
||||
|
||||
if (previousIfindex > 0 && previousIfindex != m_ifindex) {
|
||||
m_resolver->callWithArgumentList(QDBus::Block, QStringLiteral("RevertLink"),
|
||||
{QVariant::fromValue(previousIfindex)});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DnsUtilsLinux::restoreResolvers() {
|
||||
m_pendingIfname.clear();
|
||||
m_pendingResolvers.clear();
|
||||
|
||||
if (m_gatewayIfindex > 0) {
|
||||
setLinkDefaultRoute(m_gatewayIfindex, true);
|
||||
m_gatewayIfindex = 0;
|
||||
}
|
||||
|
||||
for (auto iterator = m_linkDomains.constBegin();
|
||||
iterator != m_linkDomains.constEnd(); ++iterator) {
|
||||
setLinkDomains(iterator.key(), iterator.value());
|
||||
@@ -72,7 +141,7 @@ bool DnsUtilsLinux::restoreResolvers() {
|
||||
m_linkDomains.clear();
|
||||
|
||||
/* Revert the VPN interface's DNS configuration */
|
||||
if (m_ifindex > 0) {
|
||||
if (m_ifindex > 0 && m_resolver) {
|
||||
QList<QVariant> argumentList = {QVariant::fromValue(m_ifindex)};
|
||||
QDBusPendingReply<> reply = m_resolver->asyncCallWithArgumentList(
|
||||
QStringLiteral("RevertLink"), argumentList);
|
||||
@@ -90,13 +159,17 @@ bool DnsUtilsLinux::restoreResolvers() {
|
||||
void DnsUtilsLinux::dnsCallCompleted(QDBusPendingCallWatcher* call) {
|
||||
QDBusPendingReply<> reply = *call;
|
||||
if (reply.isError()) {
|
||||
logger.error() << "Error received from the DBus service";
|
||||
logger.debug() << "DBus call failed (may be transient after systemd-resolved restart)";
|
||||
logger.debug() << "Restarting resolved to clear its query backlog";
|
||||
RouterLinux::Instance().flushDns();
|
||||
scheduleRetry();
|
||||
}
|
||||
delete call;
|
||||
}
|
||||
|
||||
void DnsUtilsLinux::setLinkDNS(int ifindex,
|
||||
const QList<QHostAddress>& resolvers) {
|
||||
if (!m_resolver) return;
|
||||
QList<DnsResolver> resolverList;
|
||||
char ifnamebuf[IF_NAMESIZE];
|
||||
const char* ifname = if_indextoname(ifindex, ifnamebuf);
|
||||
@@ -121,6 +194,7 @@ void DnsUtilsLinux::setLinkDNS(int ifindex,
|
||||
|
||||
void DnsUtilsLinux::setLinkDomains(int ifindex,
|
||||
const QList<DnsLinkDomain>& domains) {
|
||||
if (!m_resolver) return;
|
||||
char ifnamebuf[IF_NAMESIZE];
|
||||
const char* ifname = if_indextoname(ifindex, ifnamebuf);
|
||||
if (ifname) {
|
||||
@@ -144,6 +218,7 @@ void DnsUtilsLinux::setLinkDomains(int ifindex,
|
||||
}
|
||||
|
||||
void DnsUtilsLinux::setLinkDefaultRoute(int ifindex, bool enable) {
|
||||
if (!m_resolver) return;
|
||||
QList<QVariant> argumentList;
|
||||
argumentList << QVariant::fromValue(ifindex);
|
||||
argumentList << QVariant::fromValue(enable);
|
||||
@@ -156,6 +231,7 @@ void DnsUtilsLinux::setLinkDefaultRoute(int ifindex, bool enable) {
|
||||
}
|
||||
|
||||
void DnsUtilsLinux::updateLinkDomains() {
|
||||
if (!m_resolver) return;
|
||||
/* Get the list of search domains, and remove any others that might conspire
|
||||
* to satisfy DNS resolution. Unfortunately, this is a pain because Qt doesn't
|
||||
* seem to be able to demarshall complex property types.
|
||||
@@ -174,11 +250,20 @@ void DnsUtilsLinux::updateLinkDomains() {
|
||||
|
||||
void DnsUtilsLinux::dnsDomainsReceived(QDBusPendingCallWatcher* call) {
|
||||
QDBusPendingReply<QVariant> reply = *call;
|
||||
call->deleteLater();
|
||||
if (reply.isError()) {
|
||||
logger.error() << "Error retrieving the DNS domains from the DBus service";
|
||||
delete call;
|
||||
// systemd-resolved may still be starting up after a restart — retry a few times
|
||||
if (m_ifindex > 0 && m_domainRetries++ < 5) {
|
||||
logger.debug() << "systemd-resolved not ready yet, retrying DNS setup ("
|
||||
<< m_domainRetries << "/5)";
|
||||
QTimer::singleShot(500, this, &DnsUtilsLinux::updateLinkDomains);
|
||||
} else {
|
||||
logger.warning() << "Failed to configure DNS after 5 retries";
|
||||
m_domainRetries = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
m_domainRetries = 0;
|
||||
|
||||
/* Update the state of the DNS domains */
|
||||
m_linkDomains.clear();
|
||||
@@ -204,9 +289,30 @@ void DnsUtilsLinux::dnsDomainsReceived(QDBusPendingCallWatcher* call) {
|
||||
}
|
||||
|
||||
/* Add a root search domain for the new interface. */
|
||||
QList<DnsLinkDomain> newlist = {root};
|
||||
setLinkDomains(m_ifindex, newlist);
|
||||
delete call;
|
||||
if (m_ifindex > 0) {
|
||||
setLinkDomains(m_ifindex, {root});
|
||||
|
||||
/* Disable DefaultRoute on the physical gateway so systemd-resolved
|
||||
* routes all DNS through the VPN interface. */
|
||||
const int gwIdx = NetworkUtilities::getGatewayAndIface().second.index();
|
||||
if (gwIdx > 0 && gwIdx != m_ifindex && gwIdx != m_gatewayIfindex) {
|
||||
m_gatewayIfindex = gwIdx;
|
||||
setLinkDefaultRoute(gwIdx, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DnsUtilsLinux::scheduleRetry() {
|
||||
if (m_pendingIfname.isEmpty() || m_retryPending || m_domainRetries >= 5)
|
||||
return;
|
||||
m_retryPending = true;
|
||||
++m_domainRetries;
|
||||
logger.debug() << "Retrying full DNS setup (" << m_domainRetries << "/5)";
|
||||
QTimer::singleShot(1000, this, [this]() {
|
||||
m_retryPending = false;
|
||||
if (!m_pendingIfname.isEmpty())
|
||||
updateResolvers(m_pendingIfname, m_pendingResolvers);
|
||||
});
|
||||
}
|
||||
|
||||
static DnsMetatypeRegistrationProxy s_dnsMetatypeProxy;
|
||||
|
||||
@@ -6,7 +6,12 @@
|
||||
#define DNSUTILSLINUX_H
|
||||
|
||||
#include <QDBusInterface>
|
||||
#include <QScopedPointer>
|
||||
#include <QDBusPendingCallWatcher>
|
||||
#include <QDBusServiceWatcher>
|
||||
#include <QHostAddress>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
#include "daemon/dnsutils.h"
|
||||
#include "dbustypeslinux.h"
|
||||
@@ -29,13 +34,22 @@ class DnsUtilsLinux final : public DnsUtils {
|
||||
void updateLinkDomains();
|
||||
|
||||
private slots:
|
||||
void onResolverRegistered();
|
||||
void onResolverUnregistered();
|
||||
void dnsCallCompleted(QDBusPendingCallWatcher*);
|
||||
void dnsDomainsReceived(QDBusPendingCallWatcher*);
|
||||
|
||||
private:
|
||||
void scheduleRetry();
|
||||
|
||||
int m_ifindex = 0;
|
||||
int m_gatewayIfindex = 0;
|
||||
int m_domainRetries = 0;
|
||||
bool m_retryPending = false;
|
||||
QMap<int, DnsLinkDomainList> m_linkDomains;
|
||||
QDBusInterface* m_resolver = nullptr;
|
||||
QScopedPointer<QDBusInterface> m_resolver;
|
||||
QString m_pendingIfname;
|
||||
QList<QHostAddress> m_pendingResolvers;
|
||||
};
|
||||
|
||||
#endif // DNSUTILSLINUX_H
|
||||
|
||||
@@ -189,6 +189,40 @@ void LinuxFirewall::uninstallAnchor(LinuxFirewall::IPVersion ip, const QString&
|
||||
deleteChain(ip, actualChain, tableName);
|
||||
}
|
||||
|
||||
QStringList LinuxFirewall::getDNSRules(const QStringList& servers)
|
||||
{
|
||||
QStringList result;
|
||||
for (const QString& server : servers)
|
||||
{
|
||||
result << QStringLiteral("-o amn0+ -d %1 -p udp --dport 53 -j ACCEPT").arg(server);
|
||||
result << QStringLiteral("-o amn0+ -d %1 -p tcp --dport 53 -j ACCEPT").arg(server);
|
||||
result << QStringLiteral("-o tun0+ -d %1 -p udp --dport 53 -j ACCEPT").arg(server);
|
||||
result << QStringLiteral("-o tun0+ -d %1 -p tcp --dport 53 -j ACCEPT").arg(server);
|
||||
result << QStringLiteral("-o tun2+ -d %1 -p udp --dport 53 -j ACCEPT").arg(server);
|
||||
result << QStringLiteral("-o tun2+ -d %1 -p tcp --dport 53 -j ACCEPT").arg(server);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList LinuxFirewall::getAllowRule(const QStringList& servers)
|
||||
{
|
||||
QStringList result;
|
||||
for (const QString& server : servers)
|
||||
{
|
||||
result << QStringLiteral("-d %1 -j ACCEPT").arg(server);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList LinuxFirewall::getBlockRule(const QStringList& servers)
|
||||
{
|
||||
QStringList result;
|
||||
for (const QString& server : servers)
|
||||
{
|
||||
result << QStringLiteral("-d %1 -j REJECT").arg(server);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void LinuxFirewall::install()
|
||||
@@ -258,8 +292,6 @@ void LinuxFirewall::install()
|
||||
|
||||
installAnchor(IPv4, QStringLiteral("110.allowNets"), {});
|
||||
|
||||
installAnchor(Both, QStringLiteral("400.allowPIA"), {});
|
||||
|
||||
installAnchor(Both, QStringLiteral("100.blockAll"), {
|
||||
QStringLiteral("-j REJECT"),
|
||||
});
|
||||
@@ -423,33 +455,16 @@ void LinuxFirewall::updateDNSServers(const QStringList& servers)
|
||||
static QStringList existingServers {};
|
||||
|
||||
existingServers = servers;
|
||||
const QString chain = QStringLiteral("%1.320.allowDNS").arg(kAnchorName);
|
||||
executeIptables(QStringLiteral("iptables"), {QStringLiteral("-F"), chain});
|
||||
const QStringList ifaces = {
|
||||
QStringLiteral("amn0+"), QStringLiteral("tun0+"), QStringLiteral("tun2+")
|
||||
};
|
||||
for (const QString& server : servers) {
|
||||
for (const QString& iface : ifaces) {
|
||||
executeIptables(QStringLiteral("iptables"),
|
||||
{QStringLiteral("-A"), chain, QStringLiteral("-o"), iface,
|
||||
QStringLiteral("-d"), server, QStringLiteral("-p"), QStringLiteral("udp"),
|
||||
QStringLiteral("--dport"), QStringLiteral("53"), QStringLiteral("-j"), QStringLiteral("ACCEPT")});
|
||||
executeIptables(QStringLiteral("iptables"),
|
||||
{QStringLiteral("-A"), chain, QStringLiteral("-o"), iface,
|
||||
QStringLiteral("-d"), server, QStringLiteral("-p"), QStringLiteral("tcp"),
|
||||
QStringLiteral("--dport"), QStringLiteral("53"), QStringLiteral("-j"), QStringLiteral("ACCEPT")});
|
||||
}
|
||||
}
|
||||
execute(QStringLiteral("iptables -F %1.320.allowDNS").arg(kAnchorName));
|
||||
for (const QString& rule : getDNSRules(servers))
|
||||
execute(QStringLiteral("iptables -A %1.320.allowDNS %2").arg(kAnchorName, rule));
|
||||
}
|
||||
|
||||
void LinuxFirewall::updateAllowNets(const QStringList& servers)
|
||||
{
|
||||
const QString chain = QStringLiteral("%1.110.allowNets").arg(kAnchorName);
|
||||
executeIptables(QStringLiteral("iptables"), {QStringLiteral("-F"), chain});
|
||||
for (const QString& server : servers)
|
||||
executeIptables(QStringLiteral("iptables"),
|
||||
{QStringLiteral("-A"), chain, QStringLiteral("-d"), server,
|
||||
QStringLiteral("-j"), QStringLiteral("ACCEPT")});
|
||||
execute(QStringLiteral("iptables -F %1.110.allowNets").arg(kAnchorName));
|
||||
for (const QString& rule : getAllowRule(servers))
|
||||
execute(QStringLiteral("iptables -A %1.110.allowNets %2").arg(kAnchorName, rule));
|
||||
}
|
||||
|
||||
void LinuxFirewall::updateBlockNets(const QStringList& servers)
|
||||
@@ -457,12 +472,9 @@ void LinuxFirewall::updateBlockNets(const QStringList& servers)
|
||||
static QStringList existingServers {};
|
||||
|
||||
existingServers = servers;
|
||||
const QString chain = QStringLiteral("%1.120.blockNets").arg(kAnchorName);
|
||||
executeIptables(QStringLiteral("iptables"), {QStringLiteral("-F"), chain});
|
||||
for (const QString& server : servers)
|
||||
executeIptables(QStringLiteral("iptables"),
|
||||
{QStringLiteral("-A"), chain, QStringLiteral("-d"), server,
|
||||
QStringLiteral("-j"), QStringLiteral("REJECT")});
|
||||
execute(QStringLiteral("iptables -F %1.120.blockNets").arg(kAnchorName));
|
||||
for (const QString& rule : getBlockRule(servers))
|
||||
execute(QStringLiteral("iptables -A %1.120.blockNets %2").arg(kAnchorName, rule));
|
||||
}
|
||||
|
||||
int waitForExitCode(QProcess& process)
|
||||
@@ -490,25 +502,7 @@ int LinuxFirewall::execute(const QString &command, bool ignoreErrors)
|
||||
logger.debug() << "(" << exitCode << ") $ " << command;
|
||||
if (!out.isEmpty())
|
||||
logger.info() << out;
|
||||
if (!err.isEmpty())
|
||||
logger.warning() << err;
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
int LinuxFirewall::executeIptables(const QString &program, const QStringList &args, bool ignoreErrors)
|
||||
{
|
||||
QProcess p;
|
||||
p.start(program, args, QProcess::ReadOnly);
|
||||
p.closeWriteChannel();
|
||||
|
||||
int exitCode = waitForExitCode(p);
|
||||
auto out = p.readAllStandardOutput().trimmed();
|
||||
auto err = p.readAllStandardError().trimmed();
|
||||
if ((exitCode != 0 || !err.isEmpty()) && !ignoreErrors)
|
||||
logger.warning() << "(" << exitCode << ") $ " << program << args.join(QLatin1Char(' '));
|
||||
if (!out.isEmpty())
|
||||
logger.info() << out;
|
||||
if (!err.isEmpty())
|
||||
if (!err.isEmpty() && !ignoreErrors)
|
||||
logger.warning() << err;
|
||||
return exitCode;
|
||||
}
|
||||
@@ -520,14 +514,12 @@ void LinuxFirewall::setupTrafficSplitting()
|
||||
logger.warning() << "net_cls cgroup v1 not available, traffic splitting disabled";
|
||||
return;
|
||||
}
|
||||
|
||||
execute(QStringLiteral(
|
||||
"if ! grep -qE '^[0-9]+[[:space:]]+%1$' /etc/iproute2/rt_tables 2>/dev/null ; then "
|
||||
"echo '200 %1' >> /etc/iproute2/rt_tables ; fi"
|
||||
).arg(kRtableName));
|
||||
|
||||
auto cGroupDir = "/sys/fs/cgroup/net_cls/" BRAND_CODE "vpnexclusions/";
|
||||
logger.info() << "Setting up cgroup in" << cGroupDir << "for traffic splitting";
|
||||
logger.info() << "Should be setting up cgroup in" << cGroupDir << "for traffic splitting";
|
||||
execute(QStringLiteral("if [ ! -d %1 ] ; then mkdir %1 ; sleep 0.1 ; echo %2 > %1/net_cls.classid ; fi").arg(cGroupDir).arg(kCGroupId));
|
||||
// Set a rule with priority 100 (lower priority than local but higher than main/default, 0 is highest priority)
|
||||
execute(QStringLiteral("if ! ip rule list | grep -q %1 ; then ip rule add from all fwmark %1 lookup %2 pri 100 ; fi").arg(kPacketTag, kRtableName));
|
||||
@@ -536,7 +528,8 @@ void LinuxFirewall::setupTrafficSplitting()
|
||||
void LinuxFirewall::teardownTrafficSplitting()
|
||||
{
|
||||
logger.info() << "Tearing down cgroup and routing rules";
|
||||
execute(QStringLiteral("if ip rule list | grep -q %1; then ip rule del from all fwmark %1 lookup %2 2>/dev/null ; fi").arg(kPacketTag, kRtableName));
|
||||
execute(QStringLiteral("ip route flush table %1 2>/dev/null || true").arg(kRtableName));
|
||||
execute(QStringLiteral("if ip rule list | grep -q %1; then ip rule del from all fwmark %1 lookup %2 2> /dev/null ; fi").arg(kPacketTag, kRtableName));
|
||||
execute(QStringLiteral("ip route flush table %1").arg(kRtableName), true);
|
||||
execute(QStringLiteral("ip route flush cache"));
|
||||
execute(QStringLiteral("sed -i '/%1/d' /etc/iproute2/rt_tables").arg(kRtableName));
|
||||
}
|
||||
|
||||
@@ -79,10 +79,12 @@ private:
|
||||
static int unlinkChain(IPVersion ip, const QString& chain, const QString& parent, const QString& tableName = kFilterTable);
|
||||
static void installAnchor(IPVersion ip, const QString& anchor, const QStringList& rules, const QString& tableName = kFilterTable, const FilterCallbackFunc& enableFunc = {}, const FilterCallbackFunc& disableFunc = {});
|
||||
static void uninstallAnchor(IPVersion ip, const QString& anchor, const QString& tableName = kFilterTable);
|
||||
static QStringList getDNSRules(const QStringList& servers);
|
||||
static QStringList getAllowRule(const QStringList& servers);
|
||||
static QStringList getBlockRule(const QStringList& servers);
|
||||
static void setupTrafficSplitting();
|
||||
static void teardownTrafficSplitting();
|
||||
static int execute(const QString& command, bool ignoreErrors = false);
|
||||
static int executeIptables(const QString& program, const QStringList& args, bool ignoreErrors = false);
|
||||
private:
|
||||
// Chain names
|
||||
static QString kOutputChain, kRootChain, kPostRoutingChain, kPreRoutingChain;
|
||||
|
||||
@@ -167,12 +167,6 @@ bool WireguardUtilsLinux::addInterface(const InterfaceConfig& config) {
|
||||
if (!config.m_maxHandshakeAttempts.isEmpty()) {
|
||||
out << "max_handshake_attempts=" << config.m_maxHandshakeAttempts << "\n";
|
||||
}
|
||||
if (!config.m_randomTrailers.isEmpty()) {
|
||||
out << "random_trailers=" << InterfaceConfig::awgBoolToUapi(config.m_randomTrailers) << "\n";
|
||||
}
|
||||
if (!config.m_disableCookies.isEmpty()) {
|
||||
out << "disable_cookies=" << InterfaceConfig::awgBoolToUapi(config.m_disableCookies) << "\n";
|
||||
}
|
||||
|
||||
int err = uapiErrno(uapiCommand(message));
|
||||
if (err != 0) {
|
||||
@@ -269,7 +263,11 @@ bool WireguardUtilsLinux::updatePeer(const InterfaceConfig& config) {
|
||||
// Exclude the server address, except for multihop exit servers.
|
||||
if ((config.m_hopType != InterfaceConfig::MultiHopExit) &&
|
||||
(m_rtmonitor != nullptr)) {
|
||||
m_rtmonitor->addExclusionRoute(IPAddress(config.m_serverIpv4AddrIn));
|
||||
if (!config.m_serverIpv4AddrIn.isEmpty() &&
|
||||
!m_rtmonitor->addExclusionRoute(IPAddress(config.m_serverIpv4AddrIn))) {
|
||||
logger.error() << "No gateway — cannot add server exclusion route";
|
||||
return false;
|
||||
}
|
||||
m_rtmonitor->addExclusionRoute(IPAddress(config.m_serverIpv6AddrIn));
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
enum NMState {
|
||||
NM_STATE_UNKNOWN = 0,
|
||||
NM_STATE_ASLEEP = 10,
|
||||
NM_STATE_DISABLED = 10,
|
||||
NM_STATE_DISCONNECTED = 20,
|
||||
NM_STATE_DISCONNECTING = 30,
|
||||
NM_STATE_CONNECTING = 40,
|
||||
@@ -202,9 +201,18 @@ void LinuxNetworkWatcherWorker::NMStateChanged(quint32 state)
|
||||
{
|
||||
logger.debug() << "NMStateChanged " << state;
|
||||
|
||||
if (state == NM_STATE_ASLEEP || state == NM_STATE_DISABLED) {
|
||||
// NM_STATE_ASLEEP means networking just went *down* (e.g. NM tearing
|
||||
// interfaces down for suspend), not that the system woke up. Fire
|
||||
// wakeup() on the transition back out of it, once NM starts doing
|
||||
// anything again, rather than on entering it.
|
||||
if (state == NM_STATE_ASLEEP) {
|
||||
m_wasAsleep = true;
|
||||
} else if (m_wasAsleep) {
|
||||
m_wasAsleep = false;
|
||||
emit wakeup();
|
||||
} else if (state == NM_STATE_CONNECTED_GLOBAL) {
|
||||
}
|
||||
|
||||
if (state == NM_STATE_CONNECTED_GLOBAL) {
|
||||
emit networkChanged();
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,10 @@ class LinuxNetworkWatcherWorker final : public QObject {
|
||||
// initialization. When a property of them changes, we check if the access
|
||||
// point is active and unsecure.
|
||||
QStringList m_devicePaths;
|
||||
|
||||
// Set on NM_STATE_ASLEEP, cleared when NetworkManager comes back. Guards
|
||||
// wakeup() so it fires on the resume transition, not on going to sleep.
|
||||
bool m_wasAsleep = false;
|
||||
};
|
||||
|
||||
#endif // LINUXNETWORKWATCHERWORKER_H
|
||||
|
||||
@@ -165,12 +165,6 @@ bool WireguardUtilsMacos::addInterface(const InterfaceConfig& config) {
|
||||
if (!config.m_maxHandshakeAttempts.isEmpty()) {
|
||||
out << "max_handshake_attempts=" << config.m_maxHandshakeAttempts << "\n";
|
||||
}
|
||||
if (!config.m_randomTrailers.isEmpty()) {
|
||||
out << "random_trailers=" << InterfaceConfig::awgBoolToUapi(config.m_randomTrailers) << "\n";
|
||||
}
|
||||
if (!config.m_disableCookies.isEmpty()) {
|
||||
out << "disable_cookies=" << InterfaceConfig::awgBoolToUapi(config.m_disableCookies) << "\n";
|
||||
}
|
||||
|
||||
int err = uapiErrno(uapiCommand(message));
|
||||
if (err != 0) {
|
||||
|
||||
@@ -17,10 +17,7 @@ using namespace QKeychain;
|
||||
namespace {
|
||||
constexpr const char *settingsKeyTag = "settingsKeyTag";
|
||||
constexpr const char *settingsIvTag = "settingsIvTag";
|
||||
#ifndef CLIENT_KEYCHAIN_NAME_STR
|
||||
#define CLIENT_KEYCHAIN_NAME_STR "AmneziaVPN-Keychain"
|
||||
#endif
|
||||
constexpr const char *keyChainName = CLIENT_KEYCHAIN_NAME_STR;
|
||||
constexpr const char *keyChainName = "AmneziaVPN-Keychain";
|
||||
}
|
||||
|
||||
SecureQSettings::SecureQSettings(const QString &organization, const QString &application, QObject *parent, bool enableEncryption)
|
||||
|
||||
@@ -32,8 +32,6 @@ RekeyTimeout = $REKEY_TIMEOUT
|
||||
RejectAfterTime = $REJECT_AFTER_TIME
|
||||
KeepaliveTimeout = $KEEPALIVE_TIMEOUT
|
||||
MaxHandshakeAttempts = $MAX_HANDSHAKE_ATTEMPTS
|
||||
RandomTrailers = $RANDOM_TRAILERS
|
||||
DisableCookies = $DISABLE_COOKIES
|
||||
# I1 = $SPECIAL_JUNK_1
|
||||
# I2 = $SPECIAL_JUNK_2
|
||||
# I3 = $SPECIAL_JUNK_3
|
||||
|
||||
@@ -25,8 +25,6 @@ RekeyTimeout = $REKEY_TIMEOUT
|
||||
RejectAfterTime = $REJECT_AFTER_TIME
|
||||
KeepaliveTimeout = $KEEPALIVE_TIMEOUT
|
||||
MaxHandshakeAttempts = $MAX_HANDSHAKE_ATTEMPTS
|
||||
RandomTrailers = $RANDOM_TRAILERS
|
||||
DisableCookies = $DISABLE_COOKIES
|
||||
|
||||
[Peer]
|
||||
PublicKey = $WIREGUARD_SERVER_PUBLIC_KEY
|
||||
|
||||