diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6d751491..86302d56 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -255,6 +255,20 @@ jobs: env: # Keep compat with MacOS 10.15 aka Catalina by Qt 6.4 QT_VERSION: 6.4.3 + + MAC_TEAM_ID: ${{ secrets.MAC_TEAM_ID }} + + MAC_APP_CERT_CERT: ${{ secrets.MAC_APP_CERT_CERT }} + MAC_SIGNER_ID: ${{ secrets.MAC_SIGNER_ID }} + MAC_APP_CERT_PW: ${{ secrets.MAC_APP_CERT_PW }} + + MAC_INSTALLER_SIGNER_CERT: ${{ secrets.MAC_INSTALLER_SIGNER_CERT }} + MAC_INSTALLER_SIGNER_ID: ${{ secrets.MAC_INSTALLER_SIGNER_ID }} + MAC_INSTALL_CERT_PW: ${{ secrets.MAC_INSTALL_CERT_PW }} + + APPLE_DEV_EMAIL: ${{ secrets.APPLE_DEV_EMAIL }} + APPLE_DEV_PASSWORD: ${{ secrets.APPLE_DEV_PASSWORD }} + PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }} DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} @@ -295,7 +309,7 @@ jobs: - name: 'Build project' run: | export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos/bin" - bash deploy/build_macos.sh + bash deploy/build_macos.sh -n - name: 'Upload installer artifact' uses: actions/upload-artifact@v4 @@ -318,6 +332,20 @@ jobs: env: QT_VERSION: 6.8.0 + + MAC_TEAM_ID: ${{ secrets.MAC_TEAM_ID }} + + MAC_APP_CERT_CERT: ${{ secrets.MAC_APP_CERT_CERT }} + MAC_SIGNER_ID: ${{ secrets.MAC_SIGNER_ID }} + MAC_APP_CERT_PW: ${{ secrets.MAC_APP_CERT_PW }} + + MAC_INSTALLER_SIGNER_CERT: ${{ secrets.MAC_INSTALLER_SIGNER_CERT }} + MAC_INSTALLER_SIGNER_ID: ${{ secrets.MAC_INSTALLER_SIGNER_ID }} + MAC_INSTALL_CERT_PW: ${{ secrets.MAC_INSTALL_CERT_PW }} + + APPLE_DEV_EMAIL: ${{ secrets.APPLE_DEV_EMAIL }} + APPLE_DEV_PASSWORD: ${{ secrets.APPLE_DEV_PASSWORD }} + PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }} DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }} @@ -358,7 +386,7 @@ jobs: - name: 'Build project' run: | export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos/bin" - bash deploy/build_macos.sh + bash deploy/build_macos.sh -n - name: 'Upload installer artifact' uses: actions/upload-artifact@v4 diff --git a/.gitignore b/.gitignore index d3ebdc5c..cae7d9c8 100644 --- a/.gitignore +++ b/.gitignore @@ -138,3 +138,4 @@ CMakeFiles/ ios-ne-build.sh macos-ne-build.sh macos-signed-build.sh +macos-with-sign-build.sh diff --git a/client/3rd-prebuilt b/client/3rd-prebuilt index 840b7b07..522e8d33 160000 --- a/client/3rd-prebuilt +++ b/client/3rd-prebuilt @@ -1 +1 @@ -Subproject commit 840b7b070e6ac8b90dda2fac6e98859b23727c0c +Subproject commit 522e8d33a959b4d550fd0d72debf5d356a94945f diff --git a/client/cmake/macos.cmake b/client/cmake/macos.cmake index 7b7cd381..cedbce1b 100644 --- a/client/cmake/macos.cmake +++ b/client/cmake/macos.cmake @@ -18,7 +18,11 @@ set(LIBS ${LIBS} ${FW_NETWORK_EXTENSION} ) -set_target_properties(${PROJECT} PROPERTIES MACOSX_BUNDLE TRUE) +set_target_properties(${PROJECT} PROPERTIES + MACOSX_BUNDLE TRUE + MACOSX_BUNDLE_SHORT_VERSION_STRING "${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}" + MACOSX_BUNDLE_BUNDLE_VERSION "${CMAKE_PROJECT_VERSION_TWEAK}" +) set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE INTERNAL "" FORCE) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15) diff --git a/client/core/controllers/coreController.cpp b/client/core/controllers/coreController.cpp index de010fc9..5d779326 100644 --- a/client/core/controllers/coreController.cpp +++ b/client/core/controllers/coreController.cpp @@ -299,13 +299,10 @@ void CoreController::setQmlRoot() void CoreController::initApiCountryModelUpdateHandler() { - // TODO connect(m_serversModel.get(), &ServersModel::updateApiCountryModel, this, [this]() { m_apiCountryModel->updateModel(m_serversModel->getProcessedServerData("apiAvailableCountries").toJsonArray(), m_serversModel->getProcessedServerData("apiServerCountryCode").toString()); }); - connect(m_serversModel.get(), &ServersModel::updateApiServicesModel, this, - [this]() { m_apiServicesModel->updateModel(m_serversModel->getProcessedServerData("apiConfig").toJsonObject()); }); } void CoreController::initContainerModelUpdateHandler() diff --git a/client/macos/app/Info.plist b/client/macos/app/Info.plist deleted file mode 100644 index c5372ec1..00000000 --- a/client/macos/app/Info.plist +++ /dev/null @@ -1,50 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - - CFBundleAllowMixedLocalizations - - - CFBundleExecutable - ${EXECUTABLE_NAME} - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - - CFBundleInfoDictionaryVersion - 6.0 - - CFBundleName - $(PRODUCT_NAME) - - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - - CFBundleShortVersionString - $(MARKETING_VERSION) - - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - - ITSAppUsesNonExemptEncryption - - - LSApplicationCategoryType - public.app-category.utilities - - LSMinimumSystemVersion - ${MACOSX_DEPLOYMENT_TARGET} - - LSMultipleInstancesProhibited - - - NSPrincipalClass - NSApplication - - NSSupportsAutomaticGraphicsSwitching - - - diff --git a/client/ui/controllers/api/apiConfigsController.cpp b/client/ui/controllers/api/apiConfigsController.cpp index 3e2b407d..1bdd3f00 100644 --- a/client/ui/controllers/api/apiConfigsController.cpp +++ b/client/ui/controllers/api/apiConfigsController.cpp @@ -253,10 +253,10 @@ bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode, apiConfigObject.value(configKey::userCountryCode).toString(), serverCountryCode, apiConfigObject.value(configKey::serviceType).toString(), - m_apiServicesModel->getSelectedServiceProtocol(), + configKey::awg, // apiConfigObject.value(configKey::serviceProtocol).toString(), serverConfigObject.value(configKey::authData).toObject() }; - QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString(); + QString protocol = gatewayRequestData.serviceProtocol; ProtocolData protocolData = generateProtocolData(protocol); QJsonObject apiPayload = gatewayRequestData.toJsonObject(); @@ -288,9 +288,8 @@ bool ApiConfigsController::revokeNativeConfig(const QString &serverCountryCode) apiConfigObject.value(configKey::userCountryCode).toString(), serverCountryCode, apiConfigObject.value(configKey::serviceType).toString(), - m_apiServicesModel->getSelectedServiceProtocol(), - serverConfigObject.value(configKey::authData).toObject(), - QString(APPLICATION_NAME) }; + configKey::awg, // apiConfigObject.value(configKey::serviceProtocol).toString(), + serverConfigObject.value(configKey::authData).toObject() }; QJsonObject apiPayload = gatewayRequestData.toJsonObject(); diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index 3de0f035..139dc3c3 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -85,8 +85,7 @@ void VpnConnection::onConnectionStateChanged(Vpn::ConnectionState state) IpcClient::Interface()->resetIpStack(); IpcClient::Interface()->flushDns(); - if (!m_vpnConfiguration.value(config_key::configVersion).toInt() && container != DockerContainer::Awg - && container != DockerContainer::WireGuard) { + if (container != DockerContainer::Awg && container != DockerContainer::WireGuard) { QString dns1 = m_vpnConfiguration.value(config_key::dns1).toString(); QString dns2 = m_vpnConfiguration.value(config_key::dns2).toString(); diff --git a/deploy/build_macos.sh b/deploy/build_macos.sh index 68045154..5e8d7054 100644 --- a/deploy/build_macos.sh +++ b/deploy/build_macos.sh @@ -71,11 +71,54 @@ cmake --build . --config release --target all KEYCHAIN_PATH="$PROJECT_DIR/mac_sign.keychain" trap 'echo "Cleaning up mac_sign.keychain..."; security delete-keychain "$KEYCHAIN_PATH" 2>/dev/null || true; rm -f "$KEYCHAIN_PATH" 2>/dev/null || true' EXIT KEYCHAIN=$(security default-keychain -d user | tr -d '"[:space:]"') -security list-keychains -d user -s "$KEYCHAIN_PATH" "$KEYCHAIN" "$(security list-keychains -d user | tr '\n' ' ')" -security create-keychain -p "" "$KEYCHAIN_PATH" -security import "$DEPLOY_DIR/DeveloperIdApplicationCertificate.p12" -k "$KEYCHAIN_PATH" -P "$MAC_APP_CERT_PW" -T /usr/bin/codesign -security import "$DEPLOY_DIR/DeveloperIdInstallerCertificate.p12" -k "$KEYCHAIN_PATH" -P "$MAC_INSTALL_CERT_PW" -T /usr/bin/codesign + +# Build a clean list of the *existing* user key-chains. The raw output of +# security list-keychains -d user +# looks roughly like: +# " \"/Users/foo/Library/Keychains/login.keychain-db\"\n \"/Library/Keychains/System.keychain\"" +# Every entry is surrounded by quotes and indented with a few blanks. Feeding +# that verbatim back to `security list-keychains -s` inside a single quoted +# argument leads to one long, invalid path on some systems. We therefore strip +# the quotes and rely on the shell to split the string on whitespace so that +# each path becomes its own argument. + +read -ra EXISTING_KEYCHAINS <<< "$(security list-keychains -d user | tr -d '"')" + +security list-keychains -d user -s "$KEYCHAIN_PATH" "$KEYCHAIN" "${EXISTING_KEYCHAINS[@]}" +KEYCHAIN_PWD="" # Empty password keeps things simple for CI jobs +# Create, unlock and configure the temporary key-chain so that `codesign` can +# access the imported identities without triggering interactive prompts. +security create-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_PATH" +# Keep the key-chain unlocked for the duration of the job (6 hours is plenty). +security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" +security unlock-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_PATH" + +# Import the signing certificates only when the corresponding passwords are +# available in the environment. This allows the script to run in environments +# where code-signing is intentionally turned off (e.g. CI jobs that just build +# the artefacts without releasing them). + +if [ -n "${MAC_APP_CERT_PW-}" ]; then + # If the certificate is provided via environment variable, decode it. + if [ -n "${MAC_APP_CERT_CERT-}" ]; then + echo "$MAC_APP_CERT_CERT" | base64 -d > "$DEPLOY_DIR/DeveloperIdApplicationCertificate.p12" + fi + security import "$DEPLOY_DIR/DeveloperIdApplicationCertificate.p12" \ + -k "$KEYCHAIN_PATH" -P "$MAC_APP_CERT_PW" -A +fi + +if [ -n "${MAC_INSTALL_CERT_PW-}" ]; then + # Same logic for the installer certificate. + if [ -n "${MAC_INSTALLER_SIGNER_CERT-}" ]; then + echo "$MAC_INSTALLER_SIGNER_CERT" | base64 -d > "$DEPLOY_DIR/DeveloperIdInstallerCertificate.p12" + fi + security import "$DEPLOY_DIR/DeveloperIdInstallerCertificate.p12" \ + -k "$KEYCHAIN_PATH" -P "$MAC_INSTALL_CERT_PW" -A +fi + +# This certificate has no password. security import "$DEPLOY_DIR/DeveloperIDG2CA.cer" -k "$KEYCHAIN_PATH" -T /usr/bin/codesign + security list-keychains -d user -s "$KEYCHAIN_PATH" echo "____________________________________" diff --git a/service/CMakeLists.txt b/service/CMakeLists.txt index f05dbb23..5ed98ab4 100644 --- a/service/CMakeLists.txt +++ b/service/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR) set(PROJECT service) -project(${PROJECT}) +project(${PROJECT} VERSION ${AMNEZIAVPN_VERSION}) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/service/server/CMakeLists.txt b/service/server/CMakeLists.txt index 20b05acd..03128a92 100644 --- a/service/server/CMakeLists.txt +++ b/service/server/CMakeLists.txt @@ -162,7 +162,14 @@ if (WIN32 OR APPLE OR LINUX) ) endif() +set(RESOURCES) + if(WIN32) + configure_file( + ${CMAKE_CURRENT_LIST_DIR}/amneziavpn-service.rc.in + ${CMAKE_CURRENT_BINARY_DIR}/amneziavpn-service.rc + ) + set(HEADERS ${HEADERS} ${CMAKE_CURRENT_LIST_DIR}/tapcontroller_win.h ${CMAKE_CURRENT_LIST_DIR}/router_win.h @@ -203,6 +210,10 @@ if(WIN32) ${CMAKE_CURRENT_SOURCE_DIR}/../../client/platforms/windows/windowsutils.cpp ) + set(RESOURCES ${RESOURCES} + ${CMAKE_CURRENT_BINARY_DIR}/amneziavpn-service.rc + ) + set(LIBS user32 rasapi32 @@ -308,7 +319,7 @@ include_directories( ) -add_executable(${PROJECT} ${SOURCES} ${HEADERS}) +add_executable(${PROJECT} ${SOURCES} ${HEADERS} ${RESOURCES}) target_link_libraries(${PROJECT} PRIVATE Qt6::Core Qt6::Widgets Qt6::Network Qt6::RemoteObjects Qt6::Core5Compat Qt6::DBus ${LIBS}) target_compile_definitions(${PROJECT} PRIVATE "MZ_$") diff --git a/service/server/amneziavpn-service.rc.in b/service/server/amneziavpn-service.rc.in new file mode 100644 index 00000000..8ba60d38 --- /dev/null +++ b/service/server/amneziavpn-service.rc.in @@ -0,0 +1,38 @@ +#include +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#define VER_COMPANYNAME_STR "AmneziaVPN" +#define VER_FILEDESCRIPTION_STR "AmneziaVPN Service" +#define VER_INTERNALNAME_STR VER_FILEDESCRIPTION_STR +#define VER_LEGALCOPYRIGHT_STR "AmneziaVPN." +#define VER_LEGALTRADEMARKS1_STR "All Rights Reserved" +#define VER_LEGALTRADEMARKS2_STR VER_LEGALTRADEMARKS1_STR +#define VER_ORIGINALFILENAME_STR "AmneziaVPN-service.exe" +#define VER_PRODUCTNAME_STR VER_FILEDESCRIPTION_STR + +VS_VERSION_INFO VERSIONINFO +FILEVERSION @CMAKE_PROJECT_VERSION_MAJOR@,@CMAKE_PROJECT_VERSION_MINOR@,@CMAKE_PROJECT_VERSION_PATCH@,@CMAKE_PROJECT_VERSION_TWEAK@ +PRODUCTVERSION @CMAKE_PROJECT_VERSION_MAJOR@,@CMAKE_PROJECT_VERSION_MINOR@,@CMAKE_PROJECT_VERSION_PATCH@ +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", VER_COMPANYNAME_STR + VALUE "FileDescription", VER_FILEDESCRIPTION_STR + VALUE "FileVersion", "@CMAKE_PROJECT_VERSION@" + VALUE "InternalName", VER_INTERNALNAME_STR + VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR + VALUE "LegalTrademarks1", VER_LEGALTRADEMARKS1_STR + VALUE "LegalTrademarks2", VER_LEGALTRADEMARKS2_STR + VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR + VALUE "ProductName", VER_PRODUCTNAME_STR + VALUE "ProductVersion", "@CMAKE_PROJECT_VERSION@" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END