From 74802f30ed9b838f0ad55d5d167c96f44dd3d459 Mon Sep 17 00:00:00 2001 From: Nethius Date: Fri, 18 Oct 2024 13:57:38 +0400 Subject: [PATCH] feature/proxy storage bypass (#1179) * feature: added proxy storage bypass - added encryption error handling to apiController * chore: fixed include --- client/CMakeLists.txt | 2 ++ client/core/controllers/apiController.cpp | 37 +++++++++++++++++++---- client/core/defs.h | 1 + client/core/errorstrings.cpp | 1 + client/utilities.cpp | 19 ++++++++++++ client/utilities.h | 3 ++ 6 files changed, 57 insertions(+), 6 deletions(-) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 2de5db48..2ec4082c 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -26,9 +26,11 @@ add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}") add_definitions(-DPROD_AGW_PUBLIC_KEY="$ENV{PROD_AGW_PUBLIC_KEY}") add_definitions(-DPROD_PROXY_STORAGE_KEY="$ENV{PROD_PROXY_STORAGE_KEY}") +add_definitions(-DPROD_S3_ENDPOINT="$ENV{PROD_S3_ENDPOINT}") add_definitions(-DDEV_AGW_PUBLIC_KEY="$ENV{DEV_AGW_PUBLIC_KEY}") add_definitions(-DDEV_AGW_ENDPOINT="$ENV{DEV_AGW_ENDPOINT}") +add_definitions(-DDEV_S3_ENDPOINT="$ENV{DEV_S3_ENDPOINT}") if(IOS) set(PACKAGES ${PACKAGES} Multimedia) diff --git a/client/core/controllers/apiController.cpp b/client/core/controllers/apiController.cpp index 5cdaa7ae..96c28a81 100644 --- a/client/core/controllers/apiController.cpp +++ b/client/core/controllers/apiController.cpp @@ -12,6 +12,7 @@ #include "configurators/wireguard_configurator.h" #include "core/enums/apiEnums.h" #include "version.h" +#include "utilities.h" namespace { @@ -42,8 +43,6 @@ namespace constexpr char keyPayload[] = "key_payload"; } - const QStringList proxyStorageUrl = { "" }; - ErrorCode checkErrors(const QList &sslErrors, QNetworkReply *reply) { if (!sslErrors.empty()) { @@ -146,6 +145,15 @@ QStringList ApiController::getProxyUrls() QList sslErrors; QNetworkReply *reply; + QStringList proxyStorageUrl; + if (m_isDevEnvironment) { + proxyStorageUrl = QStringList { DEV_S3_ENDPOINT }; + } else { + proxyStorageUrl = QStringList { PROD_S3_ENDPOINT }; + } + + QByteArray key = m_isDevEnvironment ? DEV_AGW_PUBLIC_KEY : PROD_AGW_PUBLIC_KEY; + for (const auto &proxyStorageUrl : proxyStorageUrl) { request.setUrl(proxyStorageUrl); reply = amnApp->manager()->get(request); @@ -166,11 +174,23 @@ QStringList ApiController::getProxyUrls() EVP_PKEY *privateKey = nullptr; QByteArray responseBody; try { - QByteArray key = PROD_PROXY_STORAGE_KEY; - QSimpleCrypto::QRsa rsa; - privateKey = rsa.getPrivateKeyFromByteArray(key, ""); - responseBody = rsa.decrypt(encryptedResponseBody, privateKey, RSA_PKCS1_PADDING); + if (!m_isDevEnvironment) { + QCryptographicHash hash(QCryptographicHash::Sha512); + hash.addData(key); + QByteArray hashResult = hash.result().toHex(); + + QByteArray key = QByteArray::fromHex(hashResult.left(64)); + QByteArray iv = QByteArray::fromHex(hashResult.mid(64, 32)); + + QByteArray ba = QByteArray::fromBase64(encryptedResponseBody); + + QSimpleCrypto::QBlockCipher blockCipher; + responseBody = blockCipher.decryptAesBlockCipher(ba, key, iv); + } else { + responseBody = encryptedResponseBody; + } } catch (...) { + Utils::logException(); qCritical() << "error loading private key from environment variables or decrypting payload"; return {}; } @@ -361,6 +381,7 @@ ErrorCode ApiController::getConfigForService(const QString &installationUuid, co QSimpleCrypto::QRsa rsa; publicKey = rsa.getPublicKeyFromByteArray(rsaKey); } catch (...) { + Utils::logException(); qCritical() << "error loading public key from environment variables"; return ErrorCode::ApiMissingAgwPublicKey; } @@ -370,7 +391,9 @@ ErrorCode ApiController::getConfigForService(const QString &installationUuid, co encryptedApiPayload = blockCipher.encryptAesBlockCipher(QJsonDocument(apiPayload).toJson(), key, iv, "", salt); } catch (...) { // todo change error handling in QSimpleCrypto? + Utils::logException(); qCritical() << "error when encrypting the request body"; + return ErrorCode::ApiConfigDecryptionError; } QJsonObject requestBody; @@ -416,7 +439,9 @@ ErrorCode ApiController::getConfigForService(const QString &installationUuid, co auto responseBody = blockCipher.decryptAesBlockCipher(encryptedResponseBody, key, iv, "", salt); fillServerConfig(protocol, apiPayloadData, responseBody, serverConfig); } catch (...) { // todo change error handling in QSimpleCrypto? + Utils::logException(); qCritical() << "error when decrypting the request body"; + return ErrorCode::ApiConfigDecryptionError; } return errorCode; diff --git a/client/core/defs.h b/client/core/defs.h index 802eca45..d00d347b 100644 --- a/client/core/defs.h +++ b/client/core/defs.h @@ -108,6 +108,7 @@ namespace amnezia ApiConfigTimeoutError = 1103, ApiConfigSslError = 1104, ApiMissingAgwPublicKey = 1105, + ApiConfigDecryptionError = 1106, // QFile errors OpenError = 1200, diff --git a/client/core/errorstrings.cpp b/client/core/errorstrings.cpp index c5c0363b..49534606 100644 --- a/client/core/errorstrings.cpp +++ b/client/core/errorstrings.cpp @@ -62,6 +62,7 @@ QString errorString(ErrorCode code) { case (ErrorCode::ApiConfigSslError): errorMessage = QObject::tr("SSL error occurred"); break; case (ErrorCode::ApiConfigTimeoutError): errorMessage = QObject::tr("Server response timeout on api request"); break; case (ErrorCode::ApiMissingAgwPublicKey): errorMessage = QObject::tr("Missing AGW public key"); break; + case (ErrorCode::ApiConfigDecryptionError): errorMessage = QObject::tr("Failed to decrypt response payload"); break; // QFile errors case(ErrorCode::OpenError): errorMessage = QObject::tr("QFile error: The file could not be opened"); break; diff --git a/client/utilities.cpp b/client/utilities.cpp index 4047365f..731781b5 100644 --- a/client/utilities.cpp +++ b/client/utilities.cpp @@ -244,3 +244,22 @@ bool Utils::signalCtrl(DWORD dwProcessId, DWORD dwCtrlEvent) } #endif + +void Utils::logException(const std::exception &e) +{ + qCritical() << e.what(); + try { + std::rethrow_if_nested(e); + } catch (const std::exception &nested) { + logException(nested); + } catch (...) {} +} + +void Utils::logException(const std::exception_ptr &eptr) +{ + try { + if (eptr) std::rethrow_exception(eptr); + } catch (const std::exception &e) { + logException(e); + } catch (...) {} +} diff --git a/client/utilities.h b/client/utilities.h index 9bf8c82a..2a17a1f4 100644 --- a/client/utilities.h +++ b/client/utilities.h @@ -34,6 +34,9 @@ public: static QString certUtilPath(); static QString tun2socksPath(); + static void logException(const std::exception &e); + static void logException(const std::exception_ptr &eptr = std::current_exception()); + #ifdef Q_OS_WIN static bool signalCtrl(DWORD dwProcessId, DWORD dwCtrlEvent); #endif