From 7029968c47867fcba962f88b00051056915c0242 Mon Sep 17 00:00:00 2001 From: eugenyorbitsoftcom Date: Fri, 29 Jul 2022 10:36:54 +0600 Subject: [PATCH 01/20] SecureFormat AES-GCM --- client/client.pro | 2 + client/main.cpp | 13 ++++ client/secureformat.cpp | 169 ++++++++++++++++++++++++++++++++++++++++ client/secureformat.h | 21 +++++ client/settings.cpp | 7 +- client/settings.h | 8 +- 6 files changed, 213 insertions(+), 7 deletions(-) create mode 100644 client/secureformat.cpp create mode 100644 client/secureformat.h diff --git a/client/client.pro b/client/client.pro index 316730f93..1ec8cf1f8 100644 --- a/client/client.pro +++ b/client/client.pro @@ -40,6 +40,7 @@ HEADERS += \ managementserver.h \ platforms/linux/leakdetector.h \ protocols/protocols_defs.h \ + secureformat.h \ settings.h \ ui/notificationhandler.h \ ui/models/containers_model.h \ @@ -97,6 +98,7 @@ SOURCES += \ managementserver.cpp \ platforms/linux/leakdetector.cpp \ protocols/protocols_defs.cpp \ + secureformat.cpp \ settings.cpp \ ui/notificationhandler.cpp \ ui/models/containers_model.cpp \ diff --git a/client/main.cpp b/client/main.cpp index b1419f183..e3a1674f2 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -136,6 +136,19 @@ int main(int argc, char *argv[]) return 0; } +// QSettings oldSettings(ORGANIZATION_NAME, APPLICATION_NAME); +// if (!oldSettings.allKeys().isEmpty()) { +// QSettings newSettings(QSettings::Format::CustomFormat1, QSettings::UserScope, +// ORGANIZATION_NAME, APPLICATION_NAME); +// QString oldSettingsFileName = oldSettings.fileName(); +// QString newSettingsFileName = newSettings.fileName(); +// qDebug() << "oldSettingsFileName:" << oldSettingsFileName; +// qDebug() << "newSettingsFileName:" << newSettingsFileName; +//// qDebug() << "New config removed:" << QFile::remove(newSettingsFileName); +// qDebug() << "Old config copied:" << QFile::copy(oldSettingsFileName, newSettingsFileName); +//// qDebug() << "Old config removed:" << QFile::remove(oldSettingsFileName); +// } + Settings settings; if (settings.isSaveLogs()) { diff --git a/client/secureformat.cpp b/client/secureformat.cpp new file mode 100644 index 000000000..bd12e907e --- /dev/null +++ b/client/secureformat.cpp @@ -0,0 +1,169 @@ +#include "secureformat.h" + +#include +#include + +#include "openssl/evp.h" + +void handleErrors() { + qDebug() << "handleErrors"; +} + +int gcm_encrypt(unsigned char *plaintext, int plaintext_len, + unsigned char *key, + unsigned char *iv, int iv_len, + unsigned char *ciphertext) +{ + EVP_CIPHER_CTX *ctx; + + int len; + + int ciphertext_len; + + + /* Create and initialise the context */ + if(!(ctx = EVP_CIPHER_CTX_new())) + handleErrors(); + + /* Initialise the encryption operation. */ + if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) + handleErrors(); + + /* + * Set IV length if default 12 bytes (96 bits) is not appropriate + */ + if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) + handleErrors(); + + /* Initialise key and IV */ + if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) + handleErrors(); + + /* + * Provide the message to be encrypted, and obtain the encrypted output. + * EVP_EncryptUpdate can be called multiple times if necessary + */ + if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) + handleErrors(); + ciphertext_len = len; + + /* + * Finalise the encryption. Normally ciphertext bytes may be written at + * this stage, but this does not occur in GCM mode + */ + if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) + handleErrors(); + ciphertext_len += len; + + /* Clean up */ + EVP_CIPHER_CTX_free(ctx); + + return ciphertext_len; +} + +int gcm_decrypt(unsigned char *ciphertext, int ciphertext_len, + unsigned char *key, + unsigned char *iv, int iv_len, + unsigned char *plaintext) +{ + EVP_CIPHER_CTX *ctx; + int len; + int plaintext_len; + int ret; + + /* Create and initialise the context */ + if(!(ctx = EVP_CIPHER_CTX_new())) + handleErrors(); + + /* Initialise the decryption operation. */ + if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) + handleErrors(); + + /* Set IV length. Not necessary if this is 12 bytes (96 bits) */ + if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) + handleErrors(); + + /* Initialise key and IV */ + if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) + handleErrors(); + + /* + * Provide the message to be decrypted, and obtain the plaintext output. + * EVP_DecryptUpdate can be called multiple times if necessary + */ + if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) + handleErrors(); + plaintext_len = len; + + /* + * Finalise the decryption. A positive return value indicates success, + * anything else is a failure - the plaintext is not trustworthy. + */ + ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len); + + /* Clean up */ + EVP_CIPHER_CTX_free(ctx); + + if(ret > 0) { + /* Success */ + plaintext_len += len; + return plaintext_len; + } else { + /* Verify failed */ + return -1; + } +} + +SecureFormat::SecureFormat() +{ + m_format = QSettings::registerFormat("plist", + readSecureFile, + writeSecureFile); + qDebug() << "SecureFormat" << m_format; + + unsigned char plainText[] = "Hello world!"; + qDebug("%s", plainText); + unsigned char key[] = "12345qwerty"; + unsigned char iv[] = "000000000000"; + unsigned char chipherText[1024]; + unsigned char decryptPlainText[1024]; + gcm_encrypt(plainText, std::strlen((const char *)plainText), + key, + iv, 12, + chipherText); + qDebug("%s", chipherText); + + gcm_decrypt(chipherText, std::strlen((const char *)chipherText), + key, + iv, 12, + decryptPlainText); + qDebug("%s", decryptPlainText); +} + +bool SecureFormat::readSecureFile(QIODevice& device, QSettings::SettingsMap& map) { + if (!device.isOpen()) { + return false; + } + + QTextStream inStream(&device); + while (!inStream.atEnd()) { + QString line = inStream.readLine(); + qDebug() << "SecureFormat::readSecureFile" << line; + } + + return true; +} + +bool SecureFormat::writeSecureFile(QIODevice& device, const QSettings::SettingsMap& map) { + if (!device.isOpen()) { + return false; + } + + QTextStream outStream(&device); + + return true; +} + +const QSettings::Format& SecureFormat::format() const{ + return m_format; +} diff --git a/client/secureformat.h b/client/secureformat.h new file mode 100644 index 000000000..bb93d77e3 --- /dev/null +++ b/client/secureformat.h @@ -0,0 +1,21 @@ +#ifndef SECUREFORMAT_H +#define SECUREFORMAT_H + +#include +#include + +class SecureFormat +{ +public: + SecureFormat(); + + static bool readSecureFile(QIODevice &device, QSettings::SettingsMap &map); + static bool writeSecureFile(QIODevice &device, const QSettings::SettingsMap &map); + + const QSettings::Format& format() const; + +private: + QSettings::Format m_format; +}; + +#endif // SECUREFORMAT_H diff --git a/client/settings.cpp b/client/settings.cpp index 317df7406..e35a14ace 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -8,10 +8,15 @@ const char Settings::cloudFlareNs1[] = "1.1.1.1"; const char Settings::cloudFlareNs2[] = "1.0.0.1"; +SecureFormat Settings::m_secureFormat; + Settings::Settings(QObject* parent) : QObject(parent), - m_settings (ORGANIZATION_NAME, APPLICATION_NAME, this) + m_settings(m_secureFormat.format(), QSettings::UserScope, + ORGANIZATION_NAME, APPLICATION_NAME, this) { + qDebug() << "Settings::Settings()" << this; + qDebug() << "Settings::Settings()" << m_settings.fileName(); // Import old settings if (serversCount() == 0) { QString user = m_settings.value("Server/userName").toString(); diff --git a/client/settings.h b/client/settings.h index d5cb16396..7b0066b90 100644 --- a/client/settings.h +++ b/client/settings.h @@ -11,6 +11,7 @@ #include "core/defs.h" #include "containers/containers_defs.h" +#include "secureformat.h" using namespace amnezia; @@ -110,14 +111,9 @@ class Settings : public QObject // static constexpr char openNicNs5[] = "94.103.153.176"; // static constexpr char openNicNs13[] = "144.76.103.143"; - -public: - - - private: + static SecureFormat m_secureFormat; QSettings m_settings; - }; #endif // SETTINGS_H From 3b78c3a9295bbd63b4b294be20064d4e9e85a54c Mon Sep 17 00:00:00 2001 From: eugenyorbitsoftcom Date: Fri, 29 Jul 2022 14:58:22 +0600 Subject: [PATCH 02/20] chiperSettings --- client/main.cpp | 20 ++++++----- client/secureformat.cpp | 76 +++++++++++++++++++++++++++++------------ client/secureformat.h | 2 ++ 3 files changed, 68 insertions(+), 30 deletions(-) diff --git a/client/main.cpp b/client/main.cpp index e3a1674f2..aae9a7e3e 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -136,18 +136,22 @@ int main(int argc, char *argv[]) return 0; } -// QSettings oldSettings(ORGANIZATION_NAME, APPLICATION_NAME); -// if (!oldSettings.allKeys().isEmpty()) { -// QSettings newSettings(QSettings::Format::CustomFormat1, QSettings::UserScope, -// ORGANIZATION_NAME, APPLICATION_NAME); -// QString oldSettingsFileName = oldSettings.fileName(); -// QString newSettingsFileName = newSettings.fileName(); + QSettings oldSettings(ORGANIZATION_NAME, APPLICATION_NAME); + if (!oldSettings.allKeys().isEmpty()) { + QSettings newSettingsForPath(QSettings::Format::CustomFormat1, QSettings::UserScope, + ORGANIZATION_NAME, APPLICATION_NAME); + QString oldSettingsFileName = oldSettings.fileName(); + QString newSettingsFileName = newSettingsForPath.fileName(); + + qDebug() << "New config removed:" << QFile::remove(newSettingsFileName); + QSettings newSettings(newSettingsFileName, QSettings::Format::NativeFormat); + SecureFormat::chiperSettings(oldSettings, newSettings); + // qDebug() << "oldSettingsFileName:" << oldSettingsFileName; // qDebug() << "newSettingsFileName:" << newSettingsFileName; -//// qDebug() << "New config removed:" << QFile::remove(newSettingsFileName); // qDebug() << "Old config copied:" << QFile::copy(oldSettingsFileName, newSettingsFileName); //// qDebug() << "Old config removed:" << QFile::remove(oldSettingsFileName); -// } + } Settings settings; diff --git a/client/secureformat.cpp b/client/secureformat.cpp index bd12e907e..db632a0a6 100644 --- a/client/secureformat.cpp +++ b/client/secureformat.cpp @@ -1,6 +1,7 @@ #include "secureformat.h" #include +#include #include #include "openssl/evp.h" @@ -15,12 +16,9 @@ int gcm_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *ciphertext) { EVP_CIPHER_CTX *ctx; - int len; - int ciphertext_len; - /* Create and initialise the context */ if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); @@ -120,24 +118,6 @@ SecureFormat::SecureFormat() readSecureFile, writeSecureFile); qDebug() << "SecureFormat" << m_format; - - unsigned char plainText[] = "Hello world!"; - qDebug("%s", plainText); - unsigned char key[] = "12345qwerty"; - unsigned char iv[] = "000000000000"; - unsigned char chipherText[1024]; - unsigned char decryptPlainText[1024]; - gcm_encrypt(plainText, std::strlen((const char *)plainText), - key, - iv, 12, - chipherText); - qDebug("%s", chipherText); - - gcm_decrypt(chipherText, std::strlen((const char *)chipherText), - key, - iv, 12, - decryptPlainText); - qDebug("%s", decryptPlainText); } bool SecureFormat::readSecureFile(QIODevice& device, QSettings::SettingsMap& map) { @@ -148,7 +128,9 @@ bool SecureFormat::readSecureFile(QIODevice& device, QSettings::SettingsMap& map QTextStream inStream(&device); while (!inStream.atEnd()) { QString line = inStream.readLine(); - qDebug() << "SecureFormat::readSecureFile" << line; + qDebug() << "SecureFormat::readSecureFile: " << line; + QStringList keyValue = line.split("<=>"); + map.insert(keyValue.first(), keyValue.last()); } return true; @@ -160,10 +142,60 @@ bool SecureFormat::writeSecureFile(QIODevice& device, const QSettings::SettingsM } QTextStream outStream(&device); + auto keys = map.keys(); + for (auto key : keys) { + outStream << key << "<=>" << map.value(key).toString(); + qDebug() << "SecureFormat::writeSecureFile: " << key << "<=>" << map.value(key).toString(); + } return true; } +void SecureFormat::chiperSettings(const QSettings &oldSetting, QSettings &newSetting) { + QVariantMap keysValuesPairs; + QStringList keys = oldSetting.allKeys(); + QStringListIterator it(keys); + while ( it.hasNext() ) { + QString currentKey = it.next(); + keysValuesPairs.insert(currentKey, oldSetting.value(currentKey)); + } + + unsigned char gcmkey[] = "12345qwerty"; + unsigned char iv[] = "000000000000"; + + for (const QString& key : keys) { + QString value = keysValuesPairs.value(key).toString(); + + int plainTextSize = value.toUtf8().size(); + unsigned char* plainText = new unsigned char[plainTextSize]; + std::memcpy(plainText, value.toUtf8().constData(), plainTextSize); + + unsigned char chipherText[UINT16_MAX]; + int chipherTextSize = gcm_encrypt(plainText, plainTextSize, + gcmkey, + iv, 12, + chipherText); + QByteArray qChipherArray = QByteArray::fromRawData((const char *)chipherText, chipherTextSize); + +// unsigned char decryptPlainText[UINT16_MAX]; +// gcm_decrypt((unsigned char*)qChipherArray.data(), qChipherArray.size(), +// gcmkey, +// iv, 12, +// decryptPlainText); +// QString qDecryptPlainText = QString::fromUtf8((const char *)decryptPlainText); +// qDebug() << "qDecryptPlainText:" << qDecryptPlainText; + + newSetting.setValue(key, qChipherArray); + } + +// newSetting.sync(); +// qDebug() << "newSetting.allKeys(): " << newSetting.allKeys(); +// for (const QString& key : newSetting.allKeys()) { +// QString value = keysValuesPairs.value(key).toString(); +// qDebug() << "newSetting value: " << value; +// } +} + const QSettings::Format& SecureFormat::format() const{ return m_format; } diff --git a/client/secureformat.h b/client/secureformat.h index bb93d77e3..32e6d5991 100644 --- a/client/secureformat.h +++ b/client/secureformat.h @@ -12,6 +12,8 @@ class SecureFormat static bool readSecureFile(QIODevice &device, QSettings::SettingsMap &map); static bool writeSecureFile(QIODevice &device, const QSettings::SettingsMap &map); + static void chiperSettings(const QSettings &oldSetting, QSettings &newSetting); + const QSettings::Format& format() const; private: From e99aa868630a488b36ae964af66748630d5f4c90 Mon Sep 17 00:00:00 2001 From: eugenyorbitsoftcom Date: Mon, 1 Aug 2022 15:57:16 +0600 Subject: [PATCH 03/20] fix building project --- client/client.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/client.pro b/client/client.pro index dd75d958f..0b6b10347 100644 --- a/client/client.pro +++ b/client/client.pro @@ -319,7 +319,7 @@ ios { platforms/ios/iosglue.mm \ platforms/ios/ipaddress.cpp \ platforms/ios/ipaddressrange.cpp \ - platforms/ios/QRCodeReaderBase.mm + platforms/ios/QRCodeReaderBase.mm \ platforms/ios/QtAppDelegate.mm \ platforms/ios/MobileUtils.mm From 7e5748b3a63080e7d247eefb47f13691c82cd4b3 Mon Sep 17 00:00:00 2001 From: eugenyorbitsoftcom Date: Mon, 1 Aug 2022 16:30:57 +0600 Subject: [PATCH 04/20] fix building project --- client/client.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/client.pro b/client/client.pro index 0b6b10347..84a2d7569 100644 --- a/client/client.pro +++ b/client/client.pro @@ -309,7 +309,7 @@ ios { platforms/ios/QtAppDelegate-C-Interface.h SOURCES -= \ - platforms/ios/QRCodeReader.cpp \ + platforms/ios/QRCodeReaderBase.cpp \ platforms/ios/MobileUtils.cpp SOURCES += \ From e49b468fd530159a11a52c5df5699723a3e578c8 Mon Sep 17 00:00:00 2001 From: eugenyorbitsoftcom Date: Tue, 2 Aug 2022 15:52:03 +0600 Subject: [PATCH 05/20] writeToKeychain, readFromKeychain --- client/main.cpp | 30 +++++++------- client/platforms/ios/MobileUtils.cpp | 10 ++--- client/platforms/ios/MobileUtils.h | 3 ++ client/platforms/ios/MobileUtils.mm | 62 ++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 21 deletions(-) diff --git a/client/main.cpp b/client/main.cpp index 0991144ed..327837df1 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -38,6 +38,7 @@ #include "QZXing.h" #include "platforms/ios/QRCodeReaderBase.h" +#include "platforms/ios/MobileUtils.h" #include "debug.h" #include "defines.h" @@ -143,22 +144,23 @@ int main(int argc, char *argv[]) return 0; } - QSettings oldSettings(ORGANIZATION_NAME, APPLICATION_NAME); - if (!oldSettings.allKeys().isEmpty()) { - QSettings newSettingsForPath(QSettings::Format::CustomFormat1, QSettings::UserScope, - ORGANIZATION_NAME, APPLICATION_NAME); - QString oldSettingsFileName = oldSettings.fileName(); - QString newSettingsFileName = newSettingsForPath.fileName(); - - qDebug() << "New config removed:" << QFile::remove(newSettingsFileName); - QSettings newSettings(newSettingsFileName, QSettings::Format::NativeFormat); - SecureFormat::chiperSettings(oldSettings, newSettings); - +// QSettings oldSettings(ORGANIZATION_NAME, APPLICATION_NAME); +// if (!oldSettings.allKeys().isEmpty()) { +// QSettings newSettings(QSettings::Format::CustomFormat1, QSettings::SystemScope, +// ORGANIZATION_NAME, APPLICATION_NAME); +// QString oldSettingsFileName = oldSettings.fileName(); +// QString newSettingsFileName = newSettings.fileName(); // qDebug() << "oldSettingsFileName:" << oldSettingsFileName; // qDebug() << "newSettingsFileName:" << newSettingsFileName; -// qDebug() << "Old config copied:" << QFile::copy(oldSettingsFileName, newSettingsFileName); -//// qDebug() << "Old config removed:" << QFile::remove(oldSettingsFileName); - } + +// qDebug() << "New config removed:" << QFile::remove(newSettingsFileName); +// SecureFormat::chiperSettings(oldSettings, newSettings); +//// qDebug() << "Old config copied:" << QFile::copy(oldSettingsFileName, newSettingsFileName); +////// qDebug() << "Old config removed:" << QFile::remove(oldSettingsFileName); +// } + + MobileUtils::writeToKeychain("testKey", "12345"); + qDebug() << "MobileUtils::readFromKeychain(\"testKey\"):" << MobileUtils::readFromKeychain("testKey"); Settings settings; diff --git a/client/platforms/ios/MobileUtils.cpp b/client/platforms/ios/MobileUtils.cpp index 31b58c94e..771e78559 100644 --- a/client/platforms/ios/MobileUtils.cpp +++ b/client/platforms/ios/MobileUtils.cpp @@ -1,10 +1,6 @@ #include "MobileUtils.h" -MobileUtils::MobileUtils() -{ +void MobileUtils::shareText(const QStringList&) {} -} - -void MobileUtils::shareText(const QStringList& filesToSend) { - -} +void MobileUtils::writeToKeychain(const QString&, const QString&) {} +QString MobileUtils::readFromKeychain(const QString&) { return {}; } diff --git a/client/platforms/ios/MobileUtils.h b/client/platforms/ios/MobileUtils.h index 42aa4031a..49fcdce0d 100644 --- a/client/platforms/ios/MobileUtils.h +++ b/client/platforms/ios/MobileUtils.h @@ -12,6 +12,9 @@ class MobileUtils : public QObject { public slots: static void shareText(const QStringList& filesToSend); + + static void writeToKeychain(const QString& tag, const QString& value); + static QString readFromKeychain(const QString& tag); }; #endif // MOBILEUTILS_H diff --git a/client/platforms/ios/MobileUtils.mm b/client/platforms/ios/MobileUtils.mm index 94c7c7751..658309e3c 100644 --- a/client/platforms/ios/MobileUtils.mm +++ b/client/platforms/ios/MobileUtils.mm @@ -1,6 +1,9 @@ #include "MobileUtils.h" #include +#include + +#include static UIViewController* getViewController() { NSArray *windows = [[UIApplication sharedApplication]windows]; @@ -31,3 +34,62 @@ popController.sourceView = qtController.view; } } + +bool deleteFromKeychain(const QString& tag) { + NSData* nsTag = [tag.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *deleteQuery = @{ (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrApplicationTag: nsTag, + }; + + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)deleteQuery); + if (status != errSecSuccess) { + qDebug() << "Error deleteFromKeychain" << status; + return false; + } else { + qDebug() << "OK deleteFromKeychain"; + return true; + } +} + +void MobileUtils::writeToKeychain(const QString& tag, const QString& value) { + deleteFromKeychain(tag); + + NSData* nsValue = [value.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; + NSData* nsTag = [tag.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary* addQuery = @{ (id)kSecValueData: nsValue, + (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrApplicationTag: nsTag, + }; + + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)addQuery, NULL); + if (status != errSecSuccess) { + qDebug() << "Error writeToKeychain" << status; + } else { + qDebug() << "OK writeToKeychain"; + } +} + +QString MobileUtils::readFromKeychain(const QString& tag) { + NSData* nsValue = NULL; + NSData* nsTag = [tag.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *getQuery = @{ (id)kSecReturnData: @YES, + (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrApplicationTag: nsTag, + }; + + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)getQuery, + (CFTypeRef *)&nsValue); + if (status != errSecSuccess) { + qDebug() << "Error readFromKeychain" << status; + } else { + qDebug() << "OK readFromKeychain" << nsValue; + } + + QString result; + if (nsValue) { + result = QByteArray::fromNSData(nsValue); + CFRelease(nsValue); + } + + return result; +} From 18c0aa5c815861528d68142db4610479e94188fb Mon Sep 17 00:00:00 2001 From: eugenyorbitsoftcom Date: Wed, 3 Aug 2022 10:46:59 +0600 Subject: [PATCH 06/20] kSecClassGenericPassword --- client/platforms/ios/MobileUtils.mm | 32 ++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/client/platforms/ios/MobileUtils.mm b/client/platforms/ios/MobileUtils.mm index 658309e3c..38f06a6c8 100644 --- a/client/platforms/ios/MobileUtils.mm +++ b/client/platforms/ios/MobileUtils.mm @@ -35,10 +35,15 @@ } } +const QString service = "org.amnezia.AmneziaVPN"; + bool deleteFromKeychain(const QString& tag) { NSData* nsTag = [tag.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; - NSDictionary *deleteQuery = @{ (id)kSecClass: (id)kSecClassKey, - (id)kSecAttrApplicationTag: nsTag, + NSData* nsService = [service.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; + + NSDictionary *deleteQuery = @{ (id)kSecAttrService: nsService, + (id)kSecAttrAccount: nsTag, + (id)kSecClass: (id)kSecClassGenericPassword, }; OSStatus status = SecItemDelete((__bridge CFDictionaryRef)deleteQuery); @@ -54,11 +59,14 @@ bool deleteFromKeychain(const QString& tag) { void MobileUtils::writeToKeychain(const QString& tag, const QString& value) { deleteFromKeychain(tag); - NSData* nsValue = [value.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; NSData* nsTag = [tag.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; - NSDictionary* addQuery = @{ (id)kSecValueData: nsValue, - (id)kSecClass: (id)kSecClassKey, - (id)kSecAttrApplicationTag: nsTag, + NSData* nsService = [service.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; + NSData* nsValue = [value.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; + + NSDictionary* addQuery = @{ (id)kSecAttrService: nsService, + (id)kSecAttrAccount: nsTag, + (id)kSecClass: (id)kSecClassGenericPassword, + (id)kSecValueData: nsValue, }; OSStatus status = SecItemAdd((__bridge CFDictionaryRef)addQuery, NULL); @@ -70,11 +78,15 @@ bool deleteFromKeychain(const QString& tag) { } QString MobileUtils::readFromKeychain(const QString& tag) { - NSData* nsValue = NULL; NSData* nsTag = [tag.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; - NSDictionary *getQuery = @{ (id)kSecReturnData: @YES, - (id)kSecClass: (id)kSecClassKey, - (id)kSecAttrApplicationTag: nsTag, + NSData* nsService = [service.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; + NSData* nsValue = NULL; + + NSDictionary *getQuery = @{ (id)kSecAttrService: nsService, + (id)kSecAttrAccount: nsTag, + (id)kSecClass: (id)kSecClassGenericPassword, + (id)kSecMatchLimit: (id)kSecMatchLimitOne, + (id)kSecReturnData: @YES, }; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)getQuery, From 06682c333f3dd512b3afa3b5340fa79dabf54dc2 Mon Sep 17 00:00:00 2001 From: eugenyorbitsoftcom Date: Wed, 3 Aug 2022 10:52:59 +0600 Subject: [PATCH 07/20] remove kSecAttrService --- client/platforms/ios/MobileUtils.mm | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/client/platforms/ios/MobileUtils.mm b/client/platforms/ios/MobileUtils.mm index 38f06a6c8..4a2e43e6b 100644 --- a/client/platforms/ios/MobileUtils.mm +++ b/client/platforms/ios/MobileUtils.mm @@ -35,14 +35,10 @@ } } -const QString service = "org.amnezia.AmneziaVPN"; - bool deleteFromKeychain(const QString& tag) { NSData* nsTag = [tag.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; - NSData* nsService = [service.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; - NSDictionary *deleteQuery = @{ (id)kSecAttrService: nsService, - (id)kSecAttrAccount: nsTag, + NSDictionary *deleteQuery = @{ (id)kSecAttrAccount: nsTag, (id)kSecClass: (id)kSecClassGenericPassword, }; @@ -60,11 +56,9 @@ bool deleteFromKeychain(const QString& tag) { deleteFromKeychain(tag); NSData* nsTag = [tag.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; - NSData* nsService = [service.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; NSData* nsValue = [value.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; - NSDictionary* addQuery = @{ (id)kSecAttrService: nsService, - (id)kSecAttrAccount: nsTag, + NSDictionary* addQuery = @{ (id)kSecAttrAccount: nsTag, (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecValueData: nsValue, }; @@ -79,11 +73,9 @@ bool deleteFromKeychain(const QString& tag) { QString MobileUtils::readFromKeychain(const QString& tag) { NSData* nsTag = [tag.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; - NSData* nsService = [service.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; NSData* nsValue = NULL; - NSDictionary *getQuery = @{ (id)kSecAttrService: nsService, - (id)kSecAttrAccount: nsTag, + NSDictionary *getQuery = @{ (id)kSecAttrAccount: nsTag, (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecMatchLimit: (id)kSecMatchLimitOne, (id)kSecReturnData: @YES, From 9a180b098fcd77e99f4da023856a5ebea589df34 Mon Sep 17 00:00:00 2001 From: eugenyorbitsoftcom Date: Thu, 4 Aug 2022 11:49:00 +0600 Subject: [PATCH 08/20] try read and write chipher Settings --- client/main.cpp | 40 +++++++++++--------- client/secureformat.cpp | 84 ++++++++++++++++++++++++----------------- 2 files changed, 72 insertions(+), 52 deletions(-) diff --git a/client/main.cpp b/client/main.cpp index 327837df1..748a5e5ba 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -144,26 +144,30 @@ int main(int argc, char *argv[]) return 0; } -// QSettings oldSettings(ORGANIZATION_NAME, APPLICATION_NAME); -// if (!oldSettings.allKeys().isEmpty()) { -// QSettings newSettings(QSettings::Format::CustomFormat1, QSettings::SystemScope, -// ORGANIZATION_NAME, APPLICATION_NAME); -// QString oldSettingsFileName = oldSettings.fileName(); -// QString newSettingsFileName = newSettings.fileName(); -// qDebug() << "oldSettingsFileName:" << oldSettingsFileName; -// qDebug() << "newSettingsFileName:" << newSettingsFileName; - -// qDebug() << "New config removed:" << QFile::remove(newSettingsFileName); -// SecureFormat::chiperSettings(oldSettings, newSettings); -//// qDebug() << "Old config copied:" << QFile::copy(oldSettingsFileName, newSettingsFileName); -////// qDebug() << "Old config removed:" << QFile::remove(oldSettingsFileName); -// } - - MobileUtils::writeToKeychain("testKey", "12345"); - qDebug() << "MobileUtils::readFromKeychain(\"testKey\"):" << MobileUtils::readFromKeychain("testKey"); + { + Settings settingsTemp; + } - Settings settings; + QSettings oldSettings(ORGANIZATION_NAME, APPLICATION_NAME); + QSettings newSettings(QSettings::Format::CustomFormat1, QSettings::UserScope, + ORGANIZATION_NAME, APPLICATION_NAME); + +// QString newSettingsFileName = newSettings.fileName(); +// QFile::remove(newSettingsFileName); + + if (!oldSettings.allKeys().isEmpty() && newSettings.allKeys().isEmpty()) { + QString oldSettingsFileName = oldSettings.fileName(); + QString newSettingsFileName = newSettings.fileName(); + qDebug() << "oldSettingsFileName:" << oldSettingsFileName << QFile::exists(oldSettingsFileName) << oldSettings.isWritable(); + qDebug() << "newSettingsFileName:" << newSettingsFileName << QFile::exists(newSettingsFileName) << newSettings.isWritable(); + + SecureFormat::chiperSettings(oldSettings, newSettings); + } +// MobileUtils::writeToKeychain("testKey", "12345"); +// qDebug() << "MobileUtils::readFromKeychain(\"testKey\"):" << MobileUtils::readFromKeychain("testKey"); + + Settings settings; if (settings.isSaveLogs()) { if (!Debug::init()) { qWarning() << "Initialization of debug subsystem failed"; diff --git a/client/secureformat.cpp b/client/secureformat.cpp index db632a0a6..8b8aaee2e 100644 --- a/client/secureformat.cpp +++ b/client/secureformat.cpp @@ -10,6 +10,15 @@ void handleErrors() { qDebug() << "handleErrors"; } +int generate_key_and_iv(unsigned char *iv, unsigned char *key) { +// unsigned char key[32]; +// unsigned char iv[16]; +// EVP_BytesToKey(EVP_aes_256_gcm(), EVP_md5(), +// NULL, +// key_file_buf, key_size, 1, // const unsigned char *data, int datal, int count, +// key, iv); +} + int gcm_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, int iv_len, @@ -112,9 +121,35 @@ int gcm_decrypt(unsigned char *ciphertext, int ciphertext_len, } } +unsigned char gcmkey[] = "12345qwerty"; +unsigned char iv[] = "000000000000"; + +QByteArray encryptText(const QString& value) { + int plainTextSize = value.toUtf8().size(); + unsigned char* plainText = new unsigned char[plainTextSize]; + std::memcpy(plainText, value.toUtf8().constData(), plainTextSize); + + unsigned char chipherText[UINT16_MAX]; + int chipherTextSize = gcm_encrypt(plainText, plainTextSize, + gcmkey, + iv, 12, + chipherText); + delete[] plainText; + return QByteArray::fromRawData((const char *)chipherText, chipherTextSize); +} + +QString decryptText(const QByteArray& qEncryptArray) { + unsigned char decryptPlainText[UINT16_MAX]; + gcm_decrypt((unsigned char*)qEncryptArray.data(), qEncryptArray.size(), + gcmkey, + iv, 12, + decryptPlainText); + return QString::fromUtf8((const char *)decryptPlainText); +} + SecureFormat::SecureFormat() { - m_format = QSettings::registerFormat("plist", + m_format = QSettings::registerFormat("sconf", readSecureFile, writeSecureFile); qDebug() << "SecureFormat" << m_format; @@ -128,9 +163,13 @@ bool SecureFormat::readSecureFile(QIODevice& device, QSettings::SettingsMap& map QTextStream inStream(&device); while (!inStream.atEnd()) { QString line = inStream.readLine(); - qDebug() << "SecureFormat::readSecureFile: " << line; + QStringList keyValue = line.split("<=>"); - map.insert(keyValue.first(), keyValue.last()); + QString key = keyValue.first(); + QString value = decryptText(keyValue.last().toUtf8()); + map.insert(key, value); + + qDebug() << "SecureFormat::readSecureFile: " << key << "<=>" << value; } return true; @@ -144,8 +183,11 @@ bool SecureFormat::writeSecureFile(QIODevice& device, const QSettings::SettingsM QTextStream outStream(&device); auto keys = map.keys(); for (auto key : keys) { - outStream << key << "<=>" << map.value(key).toString(); - qDebug() << "SecureFormat::writeSecureFile: " << key << "<=>" << map.value(key).toString(); + QString value = map.value(key).toString(); + QByteArray qEncryptArray = encryptText(value); + outStream << key << "<=>" << qEncryptArray; + + qDebug() << "SecureFormat::writeSecureFile: " << key << "<=>" << qEncryptArray; } return true; @@ -160,40 +202,14 @@ void SecureFormat::chiperSettings(const QSettings &oldSetting, QSettings &newSet keysValuesPairs.insert(currentKey, oldSetting.value(currentKey)); } - unsigned char gcmkey[] = "12345qwerty"; - unsigned char iv[] = "000000000000"; - for (const QString& key : keys) { QString value = keysValuesPairs.value(key).toString(); + QByteArray qEncryptArray = encryptText(value); - int plainTextSize = value.toUtf8().size(); - unsigned char* plainText = new unsigned char[plainTextSize]; - std::memcpy(plainText, value.toUtf8().constData(), plainTextSize); - - unsigned char chipherText[UINT16_MAX]; - int chipherTextSize = gcm_encrypt(plainText, plainTextSize, - gcmkey, - iv, 12, - chipherText); - QByteArray qChipherArray = QByteArray::fromRawData((const char *)chipherText, chipherTextSize); - -// unsigned char decryptPlainText[UINT16_MAX]; -// gcm_decrypt((unsigned char*)qChipherArray.data(), qChipherArray.size(), -// gcmkey, -// iv, 12, -// decryptPlainText); -// QString qDecryptPlainText = QString::fromUtf8((const char *)decryptPlainText); -// qDebug() << "qDecryptPlainText:" << qDecryptPlainText; - - newSetting.setValue(key, qChipherArray); + newSetting.setValue(key, qEncryptArray); } -// newSetting.sync(); -// qDebug() << "newSetting.allKeys(): " << newSetting.allKeys(); -// for (const QString& key : newSetting.allKeys()) { -// QString value = keysValuesPairs.value(key).toString(); -// qDebug() << "newSetting value: " << value; -// } + newSetting.sync(); } const QSettings::Format& SecureFormat::format() const{ From 870cb26e01a3f622b8f069c529d2edea3320489e Mon Sep 17 00:00:00 2001 From: eugenyorbitsoftcom Date: Fri, 5 Aug 2022 14:15:11 +0600 Subject: [PATCH 09/20] new line --- client/secureformat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/secureformat.cpp b/client/secureformat.cpp index 8b8aaee2e..5112a6015 100644 --- a/client/secureformat.cpp +++ b/client/secureformat.cpp @@ -185,7 +185,7 @@ bool SecureFormat::writeSecureFile(QIODevice& device, const QSettings::SettingsM for (auto key : keys) { QString value = map.value(key).toString(); QByteArray qEncryptArray = encryptText(value); - outStream << key << "<=>" << qEncryptArray; + outStream << key << "<=>" << qEncryptArray << "\n"; qDebug() << "SecureFormat::writeSecureFile: " << key << "<=>" << qEncryptArray; } From 71b57bfed1fbe0cd58b248a6bcc9bb155369726c Mon Sep 17 00:00:00 2001 From: pokamest Date: Fri, 5 Aug 2022 14:31:12 +0300 Subject: [PATCH 10/20] Secure settings 2 --- client/client.pro | 2 ++ client/secure_qsettings.cpp | 47 +++++++++++++++++++++++++++ client/secure_qsettings.h | 22 +++++++++++++ client/secureformat.cpp | 65 +++++++++++++++++++------------------ client/secureformat.h | 3 ++ client/settings.cpp | 7 ++-- client/settings.h | 5 +-- 7 files changed, 113 insertions(+), 38 deletions(-) create mode 100644 client/secure_qsettings.cpp create mode 100644 client/secure_qsettings.h diff --git a/client/client.pro b/client/client.pro index 84a2d7569..0b8cf83af 100644 --- a/client/client.pro +++ b/client/client.pro @@ -41,6 +41,7 @@ HEADERS += \ platforms/ios/MobileUtils.h \ platforms/linux/leakdetector.h \ protocols/protocols_defs.h \ + secure_qsettings.h \ secureformat.h \ settings.h \ ui/notificationhandler.h \ @@ -100,6 +101,7 @@ SOURCES += \ platforms/ios/MobileUtils.cpp \ platforms/linux/leakdetector.cpp \ protocols/protocols_defs.cpp \ + secure_qsettings.cpp \ secureformat.cpp \ settings.cpp \ ui/notificationhandler.cpp \ diff --git a/client/secure_qsettings.cpp b/client/secure_qsettings.cpp new file mode 100644 index 000000000..a9beb1128 --- /dev/null +++ b/client/secure_qsettings.cpp @@ -0,0 +1,47 @@ +#include "secure_qsettings.h" +#include "secureformat.h" + +#include + +SecureQSettings::SecureQSettings(const QString &organization, const QString &application, QObject *parent) + : QObject{parent}, + m_setting(organization, application, parent) +{ + encrypted = m_setting.value("encrypted").toBool(); + + // convert settings to encrypted + if (! encrypted) { + // TODO: convert + // m_setting.sync(); + } +} + +QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue) const +{ + if (encrypted) { + QByteArray encryptedValue = m_setting.value(key, defaultValue).toByteArray(); + QByteArray decryptedValue = decryptText(encryptedValue); + + QDataStream ds(&decryptedValue, QIODevice::ReadOnly); + QVariant v; + ds >> v; + return v; + } + else { + return m_setting.value(key, defaultValue); + } +} + +void SecureQSettings::setValue(const QString &key, const QVariant &value) +{ + QByteArray decryptedValue; + { + QDataStream ds(&decryptedValue, QIODevice::WriteOnly); + ds << value; + } + + QByteArray encryptedValue = encryptText(decryptedValue); + m_setting.setValue(key, encryptedValue); +} + + diff --git a/client/secure_qsettings.h b/client/secure_qsettings.h new file mode 100644 index 000000000..a7f32f64a --- /dev/null +++ b/client/secure_qsettings.h @@ -0,0 +1,22 @@ +#ifndef SECUREQSETTINGS_H +#define SECUREQSETTINGS_H + +#include +#include + +class SecureQSettings : public QObject +{ +public: + explicit SecureQSettings(const QString &organization, const QString &application = QString(), QObject *parent = nullptr); + + QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const; + void setValue(const QString &key, const QVariant &value); + void sync() { m_setting.sync(); } + void remove(const QString &key) { m_setting.remove(key); } + +private: + QSettings m_setting; + bool encrypted {false}; +}; + +#endif // SECUREQSETTINGS_H diff --git a/client/secureformat.cpp b/client/secureformat.cpp index 5112a6015..6dfe185cf 100644 --- a/client/secureformat.cpp +++ b/client/secureformat.cpp @@ -17,6 +17,7 @@ int generate_key_and_iv(unsigned char *iv, unsigned char *key) { // NULL, // key_file_buf, key_size, 1, // const unsigned char *data, int datal, int count, // key, iv); + return 0; } int gcm_encrypt(unsigned char *plaintext, int plaintext_len, @@ -124,10 +125,10 @@ int gcm_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char gcmkey[] = "12345qwerty"; unsigned char iv[] = "000000000000"; -QByteArray encryptText(const QString& value) { - int plainTextSize = value.toUtf8().size(); +QByteArray encryptText(const QByteArray& value) { + int plainTextSize = value.size(); unsigned char* plainText = new unsigned char[plainTextSize]; - std::memcpy(plainText, value.toUtf8().constData(), plainTextSize); + std::memcpy(plainText, value.constData(), plainTextSize); unsigned char chipherText[UINT16_MAX]; int chipherTextSize = gcm_encrypt(plainText, plainTextSize, @@ -138,13 +139,13 @@ QByteArray encryptText(const QString& value) { return QByteArray::fromRawData((const char *)chipherText, chipherTextSize); } -QString decryptText(const QByteArray& qEncryptArray) { +QByteArray decryptText(const QByteArray& qEncryptArray) { unsigned char decryptPlainText[UINT16_MAX]; gcm_decrypt((unsigned char*)qEncryptArray.data(), qEncryptArray.size(), gcmkey, iv, 12, decryptPlainText); - return QString::fromUtf8((const char *)decryptPlainText); + return QByteArray::fromRawData((const char *)decryptPlainText, qEncryptArray.size()); } SecureFormat::SecureFormat() @@ -176,40 +177,40 @@ bool SecureFormat::readSecureFile(QIODevice& device, QSettings::SettingsMap& map } bool SecureFormat::writeSecureFile(QIODevice& device, const QSettings::SettingsMap& map) { - if (!device.isOpen()) { - return false; - } +// if (!device.isOpen()) { +// return false; +// } - QTextStream outStream(&device); - auto keys = map.keys(); - for (auto key : keys) { - QString value = map.value(key).toString(); - QByteArray qEncryptArray = encryptText(value); - outStream << key << "<=>" << qEncryptArray << "\n"; +// QTextStream outStream(&device); +// auto keys = map.keys(); +// for (auto key : keys) { +// QString value = map.value(key).toString(); +// QByteArray qEncryptArray = encryptText(value); +// outStream << key << "<=>" << qEncryptArray << "\n"; - qDebug() << "SecureFormat::writeSecureFile: " << key << "<=>" << qEncryptArray; - } +// qDebug() << "SecureFormat::writeSecureFile: " << key << "<=>" << qEncryptArray; +// } return true; } void SecureFormat::chiperSettings(const QSettings &oldSetting, QSettings &newSetting) { - QVariantMap keysValuesPairs; - QStringList keys = oldSetting.allKeys(); - QStringListIterator it(keys); - while ( it.hasNext() ) { - QString currentKey = it.next(); - keysValuesPairs.insert(currentKey, oldSetting.value(currentKey)); - } - - for (const QString& key : keys) { - QString value = keysValuesPairs.value(key).toString(); - QByteArray qEncryptArray = encryptText(value); - - newSetting.setValue(key, qEncryptArray); - } - - newSetting.sync(); +// QVariantMap keysValuesPairs; +// QStringList keys = oldSetting.allKeys(); +// QStringListIterator it(keys); +// while ( it.hasNext() ) { +// QString currentKey = it.next(); +// keysValuesPairs.insert(currentKey, oldSetting.value(currentKey)); +// } + +// for (const QString& key : keys) { +// QString value = keysValuesPairs.value(key).toString(); +// QByteArray qEncryptArray = encryptText(value); + +// newSetting.setValue(key, qEncryptArray); +// } + +// newSetting.sync(); } const QSettings::Format& SecureFormat::format() const{ diff --git a/client/secureformat.h b/client/secureformat.h index 32e6d5991..c49ed2148 100644 --- a/client/secureformat.h +++ b/client/secureformat.h @@ -4,6 +4,9 @@ #include #include +QByteArray encryptText(const QByteArray &value); +QByteArray decryptText(const QByteArray& qEncryptArray); + class SecureFormat { public: diff --git a/client/settings.cpp b/client/settings.cpp index e35a14ace..c8069f70f 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -8,15 +8,14 @@ const char Settings::cloudFlareNs1[] = "1.1.1.1"; const char Settings::cloudFlareNs2[] = "1.0.0.1"; -SecureFormat Settings::m_secureFormat; +//SecureFormat Settings::m_secureFormat; Settings::Settings(QObject* parent) : QObject(parent), - m_settings(m_secureFormat.format(), QSettings::UserScope, - ORGANIZATION_NAME, APPLICATION_NAME, this) + m_settings(ORGANIZATION_NAME, APPLICATION_NAME, this) { qDebug() << "Settings::Settings()" << this; - qDebug() << "Settings::Settings()" << m_settings.fileName(); +// qDebug() << "Settings::Settings()" << m_settings.fileName(); // Import old settings if (serversCount() == 0) { QString user = m_settings.value("Server/userName").toString(); diff --git a/client/settings.h b/client/settings.h index 7b0066b90..082db8912 100644 --- a/client/settings.h +++ b/client/settings.h @@ -12,6 +12,7 @@ #include "core/defs.h" #include "containers/containers_defs.h" #include "secureformat.h" +#include "secure_qsettings.h" using namespace amnezia; @@ -112,8 +113,8 @@ class Settings : public QObject // static constexpr char openNicNs13[] = "144.76.103.143"; private: - static SecureFormat m_secureFormat; - QSettings m_settings; + //static SecureFormat m_secureFormat; + SecureQSettings m_settings; }; #endif // SETTINGS_H From 1e85b25438ab1b987aacf961cc0c136dc5f7b2ff Mon Sep 17 00:00:00 2001 From: pokamest Date: Fri, 5 Aug 2022 18:59:47 +0300 Subject: [PATCH 11/20] Backup/restore config --- client/main.cpp | 16 +--- client/secure_qsettings.cpp | 87 +++++++++++++++++++--- client/secure_qsettings.h | 11 ++- client/secureformat.cpp | 64 ---------------- client/secureformat.h | 6 -- client/settings.h | 4 +- client/ui/pages_logic/AppSettingsLogic.cpp | 23 ++++++ client/ui/pages_logic/AppSettingsLogic.h | 4 + client/ui/pages_logic/StartPageLogic.cpp | 2 - client/ui/pages_logic/StartPageLogic.h | 1 - client/ui/qml/Pages/PageAppSetting.qml | 29 +++++++- client/ui/qml/Pages/PageStart.qml | 15 +++- 12 files changed, 156 insertions(+), 106 deletions(-) diff --git a/client/main.cpp b/client/main.cpp index 748a5e5ba..196d5cec9 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -148,21 +148,7 @@ int main(int argc, char *argv[]) Settings settingsTemp; } - QSettings oldSettings(ORGANIZATION_NAME, APPLICATION_NAME); - QSettings newSettings(QSettings::Format::CustomFormat1, QSettings::UserScope, - ORGANIZATION_NAME, APPLICATION_NAME); - -// QString newSettingsFileName = newSettings.fileName(); -// QFile::remove(newSettingsFileName); - - if (!oldSettings.allKeys().isEmpty() && newSettings.allKeys().isEmpty()) { - QString oldSettingsFileName = oldSettings.fileName(); - QString newSettingsFileName = newSettings.fileName(); - qDebug() << "oldSettingsFileName:" << oldSettingsFileName << QFile::exists(oldSettingsFileName) << oldSettings.isWritable(); - qDebug() << "newSettingsFileName:" << newSettingsFileName << QFile::exists(newSettingsFileName) << newSettings.isWritable(); - - SecureFormat::chiperSettings(oldSettings, newSettings); - } + // MobileUtils::writeToKeychain("testKey", "12345"); // qDebug() << "MobileUtils::readFromKeychain(\"testKey\"):" << MobileUtils::readFromKeychain("testKey"); diff --git a/client/secure_qsettings.cpp b/client/secure_qsettings.cpp index a9beb1128..b2eeecbcd 100644 --- a/client/secure_qsettings.cpp +++ b/client/secure_qsettings.cpp @@ -2,34 +2,52 @@ #include "secureformat.h" #include +#include SecureQSettings::SecureQSettings(const QString &organization, const QString &application, QObject *parent) : QObject{parent}, - m_setting(organization, application, parent) + m_setting(organization, application, parent), + encryptedKeys({"Servers/serversList"}) { - encrypted = m_setting.value("encrypted").toBool(); + encrypted = m_setting.value("Conf/encrypted").toBool(); // convert settings to encrypted if (! encrypted) { - // TODO: convert - // m_setting.sync(); + for (const QString &key : m_setting.allKeys()) { + if (encryptedKeys.contains(key)) { + const QVariant &val = value(key); + setValue(key, val); + } + } + m_setting.setValue("Conf/encrypted", true); + m_setting.sync(); + encrypted = true; } } QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue) const { - if (encrypted) { - QByteArray encryptedValue = m_setting.value(key, defaultValue).toByteArray(); + if (m_cache.contains(key)) { + return m_cache.value(key); + } + + QVariant retVal; + if (encrypted && encryptedKeys.contains(key)) { + if (!m_setting.contains(key)) return defaultValue; + + QByteArray encryptedValue = m_setting.value(key).toByteArray(); QByteArray decryptedValue = decryptText(encryptedValue); QDataStream ds(&decryptedValue, QIODevice::ReadOnly); - QVariant v; - ds >> v; - return v; + ds >> retVal; } else { - return m_setting.value(key, defaultValue); + retVal = m_setting.value(key, defaultValue); } + + m_cache.insert(key, retVal); + + return retVal; } void SecureQSettings::setValue(const QString &key, const QVariant &value) @@ -42,6 +60,55 @@ void SecureQSettings::setValue(const QString &key, const QVariant &value) QByteArray encryptedValue = encryptText(decryptedValue); m_setting.setValue(key, encryptedValue); + m_cache.insert(key, value); + + sync(); +} + +void SecureQSettings::remove(const QString &key) +{ + m_setting.remove(key); + m_cache.remove(key); + + sync(); +} + +void SecureQSettings::sync() +{ + m_setting.sync(); +} + +QByteArray SecureQSettings::backupAppConfig() const +{ + QMap cfg; + for (const QString &key : m_setting.allKeys()) { + cfg.insert(key, value(key)); + } + + QByteArray ba; + { + QDataStream ds(&ba, QIODevice::WriteOnly); + ds << cfg; + } + + return ba.toBase64(); +} + +void SecureQSettings::restoreAppConfig(const QByteArray &base64Cfg) +{ + QByteArray ba = QByteArray::fromBase64(base64Cfg); + QMap cfg; + + { + QDataStream ds(&ba, QIODevice::ReadOnly); + ds >> cfg; + } + + for (const QString &key : cfg.keys()) { + setValue(key, cfg.value(key)); + } + + sync(); } diff --git a/client/secure_qsettings.h b/client/secure_qsettings.h index a7f32f64a..113757a66 100644 --- a/client/secure_qsettings.h +++ b/client/secure_qsettings.h @@ -11,12 +11,19 @@ class SecureQSettings : public QObject QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const; void setValue(const QString &key, const QVariant &value); - void sync() { m_setting.sync(); } - void remove(const QString &key) { m_setting.remove(key); } + void remove(const QString &key); + void sync(); + + QByteArray backupAppConfig() const; + void restoreAppConfig(const QByteArray &base64Cfg); private: QSettings m_setting; bool encrypted {false}; + + mutable QMap m_cache; + + QStringList encryptedKeys; // encode only key listed here }; #endif // SECUREQSETTINGS_H diff --git a/client/secureformat.cpp b/client/secureformat.cpp index 6dfe185cf..1acdeea74 100644 --- a/client/secureformat.cpp +++ b/client/secureformat.cpp @@ -148,71 +148,7 @@ QByteArray decryptText(const QByteArray& qEncryptArray) { return QByteArray::fromRawData((const char *)decryptPlainText, qEncryptArray.size()); } -SecureFormat::SecureFormat() -{ - m_format = QSettings::registerFormat("sconf", - readSecureFile, - writeSecureFile); - qDebug() << "SecureFormat" << m_format; -} - -bool SecureFormat::readSecureFile(QIODevice& device, QSettings::SettingsMap& map) { - if (!device.isOpen()) { - return false; - } - - QTextStream inStream(&device); - while (!inStream.atEnd()) { - QString line = inStream.readLine(); - - QStringList keyValue = line.split("<=>"); - QString key = keyValue.first(); - QString value = decryptText(keyValue.last().toUtf8()); - map.insert(key, value); - - qDebug() << "SecureFormat::readSecureFile: " << key << "<=>" << value; - } - - return true; -} - -bool SecureFormat::writeSecureFile(QIODevice& device, const QSettings::SettingsMap& map) { -// if (!device.isOpen()) { -// return false; -// } - -// QTextStream outStream(&device); -// auto keys = map.keys(); -// for (auto key : keys) { -// QString value = map.value(key).toString(); -// QByteArray qEncryptArray = encryptText(value); -// outStream << key << "<=>" << qEncryptArray << "\n"; -// qDebug() << "SecureFormat::writeSecureFile: " << key << "<=>" << qEncryptArray; -// } - - return true; -} -void SecureFormat::chiperSettings(const QSettings &oldSetting, QSettings &newSetting) { -// QVariantMap keysValuesPairs; -// QStringList keys = oldSetting.allKeys(); -// QStringListIterator it(keys); -// while ( it.hasNext() ) { -// QString currentKey = it.next(); -// keysValuesPairs.insert(currentKey, oldSetting.value(currentKey)); -// } -// for (const QString& key : keys) { -// QString value = keysValuesPairs.value(key).toString(); -// QByteArray qEncryptArray = encryptText(value); -// newSetting.setValue(key, qEncryptArray); -// } - -// newSetting.sync(); -} - -const QSettings::Format& SecureFormat::format() const{ - return m_format; -} diff --git a/client/secureformat.h b/client/secureformat.h index c49ed2148..04a25b64c 100644 --- a/client/secureformat.h +++ b/client/secureformat.h @@ -12,15 +12,9 @@ class SecureFormat public: SecureFormat(); - static bool readSecureFile(QIODevice &device, QSettings::SettingsMap &map); - static bool writeSecureFile(QIODevice &device, const QSettings::SettingsMap &map); - static void chiperSettings(const QSettings &oldSetting, QSettings &newSetting); - const QSettings::Format& format() const; -private: - QSettings::Format m_format; }; #endif // SECUREFORMAT_H diff --git a/client/settings.h b/client/settings.h index 082db8912..4241f1518 100644 --- a/client/settings.h +++ b/client/settings.h @@ -112,8 +112,10 @@ class Settings : public QObject // static constexpr char openNicNs5[] = "94.103.153.176"; // static constexpr char openNicNs13[] = "144.76.103.143"; + QByteArray backupAppConfig() const { return m_settings.backupAppConfig(); } + void restoreAppConfig(const QByteArray &cfg) { m_settings.restoreAppConfig(cfg); } + private: - //static SecureFormat m_secureFormat; SecureQSettings m_settings; }; diff --git a/client/ui/pages_logic/AppSettingsLogic.cpp b/client/ui/pages_logic/AppSettingsLogic.cpp index 6429fc960..ccdb5071c 100644 --- a/client/ui/pages_logic/AppSettingsLogic.cpp +++ b/client/ui/pages_logic/AppSettingsLogic.cpp @@ -74,3 +74,26 @@ void AppSettingsLogic::onPushButtonClearLogsClicked() Debug::clearLogs(); Debug::clearServiceLogs(); } + +void AppSettingsLogic::onPushButtonBackupAppConfigClicked() +{ + uiLogic()->saveTextFile("Backup application config", "AmneziaVPN.backup", ".backup", m_settings.backupAppConfig()); +} + +void AppSettingsLogic::onPushButtonRestoreAppConfigClicked() +{ + QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open backup"), + QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.backup"); + + if (fileName.isEmpty()) return; + + QFile file(fileName); + file.open(QIODevice::ReadOnly); + QByteArray data = file.readAll(); + + m_settings.restoreAppConfig(data); + + emit uiLogic()->goToPage(Page::Vpn); + emit uiLogic()->setStartPage(Page::Vpn); +} + diff --git a/client/ui/pages_logic/AppSettingsLogic.h b/client/ui/pages_logic/AppSettingsLogic.h index b597b129b..fc9f0da7e 100644 --- a/client/ui/pages_logic/AppSettingsLogic.h +++ b/client/ui/pages_logic/AppSettingsLogic.h @@ -25,6 +25,10 @@ class AppSettingsLogic : public PageLogicBase Q_INVOKABLE void onPushButtonExportLogsClicked(); Q_INVOKABLE void onPushButtonClearLogsClicked(); + Q_INVOKABLE void onPushButtonBackupAppConfigClicked(); + Q_INVOKABLE void onPushButtonRestoreAppConfigClicked(); + + public: explicit AppSettingsLogic(UiLogic *uiLogic, QObject *parent = nullptr); ~AppSettingsLogic() = default; diff --git a/client/ui/pages_logic/StartPageLogic.cpp b/client/ui/pages_logic/StartPageLogic.cpp index e8b3f2698..c21aa6f62 100644 --- a/client/ui/pages_logic/StartPageLogic.cpp +++ b/client/ui/pages_logic/StartPageLogic.cpp @@ -24,7 +24,6 @@ StartPageLogic::StartPageLogic(UiLogic *logic, QObject *parent): m_labelWaitInfoVisible{true}, m_labelWaitInfoText{}, m_pushButtonBackFromStartVisible{true}, - m_pushButtonConnectVisible{true}, m_ipAddressPortRegex{Utils::ipAddressPortRegExp()} { @@ -41,7 +40,6 @@ void StartPageLogic::onUpdatePage() set_labelWaitInfoVisible(false); set_labelWaitInfoText(""); - set_pushButtonConnectVisible(true); set_pushButtonConnectKeyChecked(false); diff --git a/client/ui/pages_logic/StartPageLogic.h b/client/ui/pages_logic/StartPageLogic.h index f5f132f89..24bdc53fe 100644 --- a/client/ui/pages_logic/StartPageLogic.h +++ b/client/ui/pages_logic/StartPageLogic.h @@ -20,7 +20,6 @@ class StartPageLogic : public PageLogicBase AUTO_PROPERTY(bool, labelWaitInfoVisible) AUTO_PROPERTY(QString, labelWaitInfoText) AUTO_PROPERTY(bool, pushButtonBackFromStartVisible) - AUTO_PROPERTY(bool, pushButtonConnectVisible) READONLY_PROPERTY(QRegExp, ipAddressPortRegex) public: diff --git a/client/ui/qml/Pages/PageAppSetting.qml b/client/ui/qml/Pages/PageAppSetting.qml index b795ceb55..7e8d415ab 100644 --- a/client/ui/qml/Pages/PageAppSetting.qml +++ b/client/ui/qml/Pages/PageAppSetting.qml @@ -107,7 +107,7 @@ PageBase { BlueButtonType { Layout.fillWidth: true - Layout.topMargin: 15 + Layout.topMargin: 10 Layout.preferredHeight: 41 text: qsTr("Export logs") onClicked: { @@ -117,7 +117,7 @@ PageBase { BlueButtonType { Layout.fillWidth: true - Layout.topMargin: 15 + Layout.topMargin: 10 Layout.preferredHeight: 41 property string start_text: qsTr("Clear logs") @@ -135,6 +135,31 @@ PageBase { AppSettingsLogic.onPushButtonClearLogsClicked() } } + + LabelType { + Layout.fillWidth: true + Layout.topMargin: 30 + text: qsTr("Backup and restore configuration") + } + + BlueButtonType { + Layout.fillWidth: true + Layout.topMargin: 10 + Layout.preferredHeight: 41 + text: qsTr("Backup app config") + onClicked: { + AppSettingsLogic.onPushButtonBackupAppConfigClicked() + } + } + BlueButtonType { + Layout.fillWidth: true + Layout.topMargin: 10 + Layout.preferredHeight: 41 + text: qsTr("Restore app config") + onClicked: { + AppSettingsLogic.onPushButtonRestoreAppConfigClicked() + } + } } } diff --git a/client/ui/qml/Pages/PageStart.qml b/client/ui/qml/Pages/PageStart.qml index 3ff11a863..ab53792d2 100644 --- a/client/ui/qml/Pages/PageStart.qml +++ b/client/ui/qml/Pages/PageStart.qml @@ -119,7 +119,6 @@ PageBase { anchors.topMargin: 40 text: qsTr("Open file") - visible: StartPageLogic.pushButtonConnectVisible onClicked: { StartPageLogic.onPushButtonImportOpenFile() } @@ -133,7 +132,6 @@ PageBase { anchors.topMargin: 10 text: qsTr("Scan QR code") - visible: StartPageLogic.pushButtonConnectVisible onClicked: { if (Qt.platform.os == "ios") { UiLogic.goToPage(PageEnum.QrDecoderIos) @@ -144,7 +142,19 @@ PageBase { enabled: StartPageLogic.pushButtonConnectEnabled } + BlueButtonType { + id: btn_restore_cfg + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: qr_code_import.bottom + anchors.topMargin: 30 + visible: UiLogic.pagesStackDepth == 1 + enabled: StartPageLogic.pushButtonConnectEnabled + text: qsTr("Restore app config") + onClicked: { + AppSettingsLogic.onPushButtonRestoreAppConfigClicked() + } + } } @@ -270,7 +280,6 @@ PageBase { anchors.topMargin: 10 text: StartPageLogic.pushButtonConnectText - visible: StartPageLogic.pushButtonConnectVisible onClicked: { StartPageLogic.onPushButtonConnect() } From 585de53148ef9abbcb0817cbbd47b0a96d874617 Mon Sep 17 00:00:00 2001 From: pokamest Date: Sat, 6 Aug 2022 19:47:29 +0300 Subject: [PATCH 12/20] Secure settings refactoring --- client/client.pro | 4 +- ...secureformat.cpp => encryption_helper.cpp} | 63 ++++++++----------- client/encryption_helper.h | 31 +++++++++ client/secure_qsettings.cpp | 62 ++++++++++++++---- client/secure_qsettings.h | 13 +++- client/secureformat.h | 20 ------ client/settings.h | 2 +- 7 files changed, 122 insertions(+), 73 deletions(-) rename client/{secureformat.cpp => encryption_helper.cpp} (70%) create mode 100644 client/encryption_helper.h delete mode 100644 client/secureformat.h diff --git a/client/client.pro b/client/client.pro index 0b8cf83af..9d2180f75 100644 --- a/client/client.pro +++ b/client/client.pro @@ -37,12 +37,12 @@ HEADERS += \ core/servercontroller.h \ debug.h \ defines.h \ + encryption_helper.h \ managementserver.h \ platforms/ios/MobileUtils.h \ platforms/linux/leakdetector.h \ protocols/protocols_defs.h \ secure_qsettings.h \ - secureformat.h \ settings.h \ ui/notificationhandler.h \ ui/models/containers_model.h \ @@ -96,13 +96,13 @@ SOURCES += \ core/server_defs.cpp \ core/servercontroller.cpp \ debug.cpp \ + encryption_helper.cpp \ main.cpp \ managementserver.cpp \ platforms/ios/MobileUtils.cpp \ platforms/linux/leakdetector.cpp \ protocols/protocols_defs.cpp \ secure_qsettings.cpp \ - secureformat.cpp \ settings.cpp \ ui/notificationhandler.cpp \ ui/models/containers_model.cpp \ diff --git a/client/secureformat.cpp b/client/encryption_helper.cpp similarity index 70% rename from client/secureformat.cpp rename to client/encryption_helper.cpp index 1acdeea74..6c1bffda8 100644 --- a/client/secureformat.cpp +++ b/client/encryption_helper.cpp @@ -1,4 +1,4 @@ -#include "secureformat.h" +#include "encryption_helper.h" #include #include @@ -6,6 +6,25 @@ #include "openssl/evp.h" +int gcm_encrypt(const char *plaintext, int plaintext_len, + const char *key, const char *iv, int iv_len, + char *ciphertext) +{ + return gcm_encrypt((uchar*)plaintext, plaintext_len, + (uchar*)key, (uchar*)iv, iv_len, + (uchar*)ciphertext); +} + +int gcm_decrypt(const char *ciphertext, int ciphertext_len, + const char *key, + const char *iv, int iv_len, + char *plaintext) +{ + return gcm_decrypt((uchar*)ciphertext, ciphertext_len, + (uchar*)key, (uchar*)iv, iv_len, + (uchar*)plaintext); +} + void handleErrors() { qDebug() << "handleErrors"; } @@ -20,9 +39,9 @@ int generate_key_and_iv(unsigned char *iv, unsigned char *key) { return 0; } -int gcm_encrypt(unsigned char *plaintext, int plaintext_len, - unsigned char *key, - unsigned char *iv, int iv_len, +int gcm_encrypt(const unsigned char *plaintext, int plaintext_len, + const unsigned char *key, + const unsigned char *iv, int iv_len, unsigned char *ciphertext) { EVP_CIPHER_CTX *ctx; @@ -69,9 +88,9 @@ int gcm_encrypt(unsigned char *plaintext, int plaintext_len, return ciphertext_len; } -int gcm_decrypt(unsigned char *ciphertext, int ciphertext_len, - unsigned char *key, - unsigned char *iv, int iv_len, +int gcm_decrypt(const unsigned char *ciphertext, int ciphertext_len, + const unsigned char *key, + const unsigned char *iv, int iv_len, unsigned char *plaintext) { EVP_CIPHER_CTX *ctx; @@ -122,33 +141,3 @@ int gcm_decrypt(unsigned char *ciphertext, int ciphertext_len, } } -unsigned char gcmkey[] = "12345qwerty"; -unsigned char iv[] = "000000000000"; - -QByteArray encryptText(const QByteArray& value) { - int plainTextSize = value.size(); - unsigned char* plainText = new unsigned char[plainTextSize]; - std::memcpy(plainText, value.constData(), plainTextSize); - - unsigned char chipherText[UINT16_MAX]; - int chipherTextSize = gcm_encrypt(plainText, plainTextSize, - gcmkey, - iv, 12, - chipherText); - delete[] plainText; - return QByteArray::fromRawData((const char *)chipherText, chipherTextSize); -} - -QByteArray decryptText(const QByteArray& qEncryptArray) { - unsigned char decryptPlainText[UINT16_MAX]; - gcm_decrypt((unsigned char*)qEncryptArray.data(), qEncryptArray.size(), - gcmkey, - iv, 12, - decryptPlainText); - return QByteArray::fromRawData((const char *)decryptPlainText, qEncryptArray.size()); -} - - - - - diff --git a/client/encryption_helper.h b/client/encryption_helper.h new file mode 100644 index 000000000..ba9214087 --- /dev/null +++ b/client/encryption_helper.h @@ -0,0 +1,31 @@ +#ifndef ENCRYPTION_HELPER_H +#define ENCRYPTION_HELPER_H + +#include +#include + + + +int gcm_encrypt(const char *plaintext, int plaintext_len, + const char *key, + const char *iv, int iv_len, + char *ciphertext); + +int gcm_decrypt(const char *ciphertext, int ciphertext_len, + const char *key, + const char *iv, int iv_len, + char *plaintext); + + +int gcm_encrypt(const unsigned char *plaintext, int plaintext_len, + const unsigned char *key, + const unsigned char *iv, int iv_len, + unsigned char *ciphertext); + +int gcm_decrypt(const unsigned char *ciphertext, int ciphertext_len, + const unsigned char *key, + const unsigned char *iv, int iv_len, + unsigned char *plaintext); + + +#endif // ENCRYPTION_HELPER_H diff --git a/client/secure_qsettings.cpp b/client/secure_qsettings.cpp index b2eeecbcd..8faed6b15 100644 --- a/client/secure_qsettings.cpp +++ b/client/secure_qsettings.cpp @@ -1,5 +1,5 @@ #include "secure_qsettings.h" -#include "secureformat.h" +#include "encryption_helper.h" #include #include @@ -9,10 +9,18 @@ SecureQSettings::SecureQSettings(const QString &organization, const QString &app m_setting(organization, application, parent), encryptedKeys({"Servers/serversList"}) { - encrypted = m_setting.value("Conf/encrypted").toBool(); + // load keys from system key storage +#ifdef Q_OS_IOS + key = MobileUtils::readFromKeychain(settingsKeyTag); + iv = MobileUtils::readFromKeychain(settingsIvTag); +#endif + key = "12345qwerty00000"; + iv = "000000000000000"; + + bool encrypted = m_setting.value("Conf/encrypted").toBool(); // convert settings to encrypted - if (! encrypted) { + if (encryptionRequired() && ! encrypted) { for (const QString &key : m_setting.allKeys()) { if (encryptedKeys.contains(key)) { const QVariant &val = value(key); @@ -21,7 +29,6 @@ SecureQSettings::SecureQSettings(const QString &organization, const QString &app } m_setting.setValue("Conf/encrypted", true); m_setting.sync(); - encrypted = true; } } @@ -32,7 +39,7 @@ QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue } QVariant retVal; - if (encrypted && encryptedKeys.contains(key)) { + if (encryptionRequired() && encryptedKeys.contains(key)) { if (!m_setting.contains(key)) return defaultValue; QByteArray encryptedValue = m_setting.value(key).toByteArray(); @@ -52,16 +59,21 @@ QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue void SecureQSettings::setValue(const QString &key, const QVariant &value) { - QByteArray decryptedValue; - { - QDataStream ds(&decryptedValue, QIODevice::WriteOnly); - ds << value; + if (encryptionRequired() && encryptedKeys.contains(key)) { + QByteArray decryptedValue; + { + QDataStream ds(&decryptedValue, QIODevice::WriteOnly); + ds << value; + } + + QByteArray encryptedValue = encryptText(decryptedValue); + m_setting.setValue(key, encryptedValue); + } + else { + m_setting.setValue(key, value); } - QByteArray encryptedValue = encryptText(decryptedValue); - m_setting.setValue(key, encryptedValue); m_cache.insert(key, value); - sync(); } @@ -112,3 +124,29 @@ void SecureQSettings::restoreAppConfig(const QByteArray &base64Cfg) } +QByteArray SecureQSettings::encryptText(const QByteArray& value) const { + char cipherText[UINT16_MAX]; + int cipherTextSize = gcm_encrypt(value.constData(), value.size(), + key.constData(), iv.constData(), iv_len, cipherText); + + return QByteArray::fromRawData((const char *)cipherText, cipherTextSize); +} + +QByteArray SecureQSettings::decryptText(const QByteArray& ba) const { + char decryptPlainText[UINT16_MAX]; + gcm_decrypt(ba.data(), ba.size(), + key.constData(), iv.constData(), iv_len, decryptPlainText); + + return QByteArray::fromRawData(decryptPlainText, ba.size()); +} + +bool SecureQSettings::encryptionRequired() const +{ +#if defined Q_OS_ANDROID || defined Q_OS_IOS + return true; +#endif + + return false; +} + + diff --git a/client/secure_qsettings.h b/client/secure_qsettings.h index 113757a66..3fcd4ed7c 100644 --- a/client/secure_qsettings.h +++ b/client/secure_qsettings.h @@ -4,6 +4,9 @@ #include #include +constexpr const char* settingsKeyTag = "settingsKeyTag"; +constexpr const char* settingsIvTag = "settingsIvTag"; + class SecureQSettings : public QObject { public: @@ -17,13 +20,21 @@ class SecureQSettings : public QObject QByteArray backupAppConfig() const; void restoreAppConfig(const QByteArray &base64Cfg); + QByteArray encryptText(const QByteArray &value) const; + QByteArray decryptText(const QByteArray& ba) const; + + bool encryptionRequired() const; + private: QSettings m_setting; - bool encrypted {false}; mutable QMap m_cache; QStringList encryptedKeys; // encode only key listed here + + QByteArray key; + QByteArray iv; + int iv_len {16}; }; #endif // SECUREQSETTINGS_H diff --git a/client/secureformat.h b/client/secureformat.h deleted file mode 100644 index 04a25b64c..000000000 --- a/client/secureformat.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef SECUREFORMAT_H -#define SECUREFORMAT_H - -#include -#include - -QByteArray encryptText(const QByteArray &value); -QByteArray decryptText(const QByteArray& qEncryptArray); - -class SecureFormat -{ -public: - SecureFormat(); - - - - -}; - -#endif // SECUREFORMAT_H diff --git a/client/settings.h b/client/settings.h index 4241f1518..39c9919c0 100644 --- a/client/settings.h +++ b/client/settings.h @@ -11,7 +11,7 @@ #include "core/defs.h" #include "containers/containers_defs.h" -#include "secureformat.h" +#include "encryption_helper.h" #include "secure_qsettings.h" using namespace amnezia; From 42398950e42a77acaf1e4a06fa0eb92e59ce0029 Mon Sep 17 00:00:00 2001 From: pokamest Date: Tue, 16 Aug 2022 08:28:41 -0700 Subject: [PATCH 13/20] Fix for iOS --- client/secure_qsettings.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/secure_qsettings.cpp b/client/secure_qsettings.cpp index 8faed6b15..0b2f138ea 100644 --- a/client/secure_qsettings.cpp +++ b/client/secure_qsettings.cpp @@ -1,5 +1,6 @@ #include "secure_qsettings.h" #include "encryption_helper.h" +#include "platforms/ios/MobileUtils.h" #include #include @@ -11,8 +12,8 @@ SecureQSettings::SecureQSettings(const QString &organization, const QString &app { // load keys from system key storage #ifdef Q_OS_IOS - key = MobileUtils::readFromKeychain(settingsKeyTag); - iv = MobileUtils::readFromKeychain(settingsIvTag); + key = QByteArray::fromBase64(MobileUtils::readFromKeychain(settingsKeyTag).toUtf8()); + iv = QByteArray::fromBase64(MobileUtils::readFromKeychain(settingsIvTag).toUtf8()); #endif key = "12345qwerty00000"; iv = "000000000000000"; From b5890340e357124e7b691e59f03323b92b2766ca Mon Sep 17 00:00:00 2001 From: pokamest Date: Tue, 23 Aug 2022 22:47:23 +0300 Subject: [PATCH 14/20] Secure settings rework --- client/3rd/QSimpleCrypto/QSimpleCrypto.pri | 18 + client/3rd/QSimpleCrypto/include/QAead.h | 87 +++++ .../3rd/QSimpleCrypto/include/QBlockCipher.h | 83 ++++ .../3rd/QSimpleCrypto/include/QCryptoError.h | 45 +++ client/3rd/QSimpleCrypto/include/QRsa.h | 104 +++++ .../include/QSimpleCrypto_global.h | 9 + client/3rd/QSimpleCrypto/include/QX509.h | 87 +++++ client/3rd/QSimpleCrypto/include/QX509Store.h | 120 ++++++ client/3rd/QSimpleCrypto/sources/QAead.cpp | 364 ++++++++++++++++++ .../QSimpleCrypto/sources/QBlockCipher.cpp | 184 +++++++++ .../QSimpleCrypto/sources/QCryptoError.cpp | 6 + client/3rd/QSimpleCrypto/sources/QRsa.cpp | 274 +++++++++++++ client/3rd/QSimpleCrypto/sources/QX509.cpp | 234 +++++++++++ .../3rd/QSimpleCrypto/sources/QX509Store.cpp | 176 +++++++++ client/client.pro | 5 +- client/encryption_helper.cpp | 143 ------- client/encryption_helper.h | 31 -- client/secure_qsettings.cpp | 103 +++-- client/secure_qsettings.h | 11 +- client/settings.cpp | 1 - client/settings.h | 1 - 21 files changed, 1863 insertions(+), 223 deletions(-) create mode 100644 client/3rd/QSimpleCrypto/QSimpleCrypto.pri create mode 100644 client/3rd/QSimpleCrypto/include/QAead.h create mode 100644 client/3rd/QSimpleCrypto/include/QBlockCipher.h create mode 100644 client/3rd/QSimpleCrypto/include/QCryptoError.h create mode 100644 client/3rd/QSimpleCrypto/include/QRsa.h create mode 100644 client/3rd/QSimpleCrypto/include/QSimpleCrypto_global.h create mode 100644 client/3rd/QSimpleCrypto/include/QX509.h create mode 100644 client/3rd/QSimpleCrypto/include/QX509Store.h create mode 100644 client/3rd/QSimpleCrypto/sources/QAead.cpp create mode 100644 client/3rd/QSimpleCrypto/sources/QBlockCipher.cpp create mode 100644 client/3rd/QSimpleCrypto/sources/QCryptoError.cpp create mode 100644 client/3rd/QSimpleCrypto/sources/QRsa.cpp create mode 100644 client/3rd/QSimpleCrypto/sources/QX509.cpp create mode 100644 client/3rd/QSimpleCrypto/sources/QX509Store.cpp delete mode 100644 client/encryption_helper.cpp delete mode 100644 client/encryption_helper.h diff --git a/client/3rd/QSimpleCrypto/QSimpleCrypto.pri b/client/3rd/QSimpleCrypto/QSimpleCrypto.pri new file mode 100644 index 000000000..99a1c1293 --- /dev/null +++ b/client/3rd/QSimpleCrypto/QSimpleCrypto.pri @@ -0,0 +1,18 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/include/QAead.h \ + $$PWD/include/QBlockCipher.h \ + $$PWD/include/QCryptoError.h \ + $$PWD/include/QRsa.h \ + $$PWD/include/QSimpleCrypto_global.h \ + $$PWD/include/QX509.h \ + $$PWD/include/QX509Store.h + +SOURCES += \ + $$PWD/sources/QAead.cpp \ + $$PWD/sources/QBlockCipher.cpp \ + $$PWD/sources/QCryptoError.cpp \ + $$PWD/sources/QRsa.cpp \ + $$PWD/sources/QX509.cpp \ + $$PWD/sources/QX509Store.cpp diff --git a/client/3rd/QSimpleCrypto/include/QAead.h b/client/3rd/QSimpleCrypto/include/QAead.h new file mode 100644 index 000000000..11f60b31f --- /dev/null +++ b/client/3rd/QSimpleCrypto/include/QAead.h @@ -0,0 +1,87 @@ +/** + * Copyright 2021 BrutalWizard (https://github.com/bru74lw1z4rd). All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution +**/ + +#ifndef QAEAD_H +#define QAEAD_H + +#include "QSimpleCrypto_global.h" + +#include + +#include + +#include +#include +#include +#include + +#include "QCryptoError.h" + +// clang-format off +namespace QSimpleCrypto +{ + class QSIMPLECRYPTO_EXPORT QAead { + public: + QAead(); + + /// + /// \brief encryptAesGcm - Function encrypts data with Gcm algorithm. + /// \param data - Data that will be encrypted. + /// \param key - AES key. + /// \param iv - Initialization vector. + /// \param tag - Authorization tag. + /// \param aad - Additional authenticated data. Must be nullptr, if not used. + /// \param cipher - Can be used with OpenSSL EVP_CIPHER (gcm) - 128, 192, 256. Example: EVP_aes_256_gcm(). + /// \return Returns encrypted data or "", if error happened. + /// + QByteArray encryptAesGcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad = "", const EVP_CIPHER* cipher = EVP_aes_256_gcm()); + + /// + /// \brief decryptAesGcm - Function decrypts data with Gcm algorithm. + /// \param data - Data that will be decrypted + /// \param key - AES key + /// \param iv - Initialization vector + /// \param tag - Authorization tag + /// \param aad - Additional authenticated data. Must be nullptr, if not used + /// \param cipher - Can be used with OpenSSL EVP_CIPHER (gcm) - 128, 192, 256. Example: EVP_aes_256_gcm() + /// \return Returns decrypted data or "", if error happened. + /// + QByteArray decryptAesGcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad = "", const EVP_CIPHER* cipher = EVP_aes_256_gcm()); + + /// + /// \brief encryptAesCcm - Function encrypts data with Ccm algorithm. + /// \param data - Data that will be encrypted. + /// \param key - AES key. + /// \param iv - Initialization vector. + /// \param tag - Authorization tag. + /// \param aad - Additional authenticated data. Must be nullptr, if not used. + /// \param cipher - Can be used with OpenSSL EVP_CIPHER (ccm) - 128, 192, 256. Example: EVP_aes_256_ccm(). + /// \return Returns encrypted data or "", if error happened. + /// + QByteArray encryptAesCcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad = "", const EVP_CIPHER* cipher = EVP_aes_256_ccm()); + + /// + /// \brief decryptAesCcm - Function decrypts data with Ccm algorithm. + /// \param data - Data that will be decrypted. + /// \param key - AES key. + /// \param iv - Initialization vector. + /// \param tag - Authorization tag. + /// \param aad - Additional authenticated data. Must be nullptr, if not used. + /// \param cipher - Can be used with OpenSSL EVP_CIPHER (ccm) - 128, 192, 256. Example: EVP_aes_256_ccm(). + /// \return Returns decrypted data or "", if error happened. + /// + QByteArray decryptAesCcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad = "", const EVP_CIPHER* cipher = EVP_aes_256_ccm()); + + /// + /// \brief error - Error handler class. + /// + QCryptoError error; + }; +} // namespace QSimpleCrypto + +#endif // QAEAD_H diff --git a/client/3rd/QSimpleCrypto/include/QBlockCipher.h b/client/3rd/QSimpleCrypto/include/QBlockCipher.h new file mode 100644 index 000000000..af57b650f --- /dev/null +++ b/client/3rd/QSimpleCrypto/include/QBlockCipher.h @@ -0,0 +1,83 @@ +/** + * Copyright 2021 BrutalWizard (https://github.com/bru74lw1z4rd). All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution +**/ + +#ifndef QBLOCKCIPHER_H +#define QBLOCKCIPHER_H + +#include "QSimpleCrypto_global.h" + +#include + +#include + +#include +#include +#include +#include + +#include "QCryptoError.h" + +// clang-format off +namespace QSimpleCrypto +{ + class QSIMPLECRYPTO_EXPORT QBlockCipher { + + #define Aes128Rounds 10 + #define Aes192Rounds 12 + #define Aes256Rounds 14 + + public: + QBlockCipher(); + + /// + /// \brief generateRandomBytes - Function generates random bytes by size. + /// \param size - Size of generated bytes. + /// \return Returns random bytes. + /// + QByteArray generateRandomBytes(const int& size); + + /// + /// \brief encryptAesBlockCipher - Function encrypts data with Aes Block Cipher algorithm. + /// \param data - Data that will be encrypted. + /// \param key - AES key. + /// \param iv - Initialization vector. + /// \param password - Encryption password. + /// \param salt - Random delta. + /// \param rounds - Transformation rounds. + /// \param chiper - Can be used with OpenSSL EVP_CIPHER (ecb, cbc, cfb, ofb, ctr) - 128, 192, 256. Example: EVP_aes_256_cbc(). + /// \param md - Hash algroitm (OpenSSL EVP_MD). Example: EVP_sha512(). + /// \return Returns decrypted data or "", if error happened. + /// + QByteArray encryptAesBlockCipher(QByteArray data, QByteArray key, + QByteArray iv = "", const int& rounds = Aes256Rounds, + const EVP_CIPHER* cipher = EVP_aes_256_cbc(), const EVP_MD* md = EVP_sha512()); + + /// + /// \brief decryptAesBlockCipher - Function decrypts data with Aes Block Cipher algorithm. + /// \param data - Data that will be decrypted. + /// \param key - AES key. + /// \param iv - Initialization vector. + /// \param password - Decryption password. + /// \param salt - Random delta. + /// \param rounds - Transformation rounds. + /// \param chiper - Can be used with OpenSSL EVP_CIPHER (ecb, cbc, cfb, ofb, ctr) - 128, 192, 256. Example: EVP_aes_256_cbc(). + /// \param md - Hash algroitm (OpenSSL EVP_MD). Example: EVP_sha512(). + /// \return Returns decrypted data or "", if error happened. + /// + QByteArray decryptAesBlockCipher(QByteArray data, QByteArray key, + QByteArray iv = "", const int& rounds = Aes256Rounds, + const EVP_CIPHER* cipher = EVP_aes_256_cbc(), const EVP_MD* md = EVP_sha512()); + + /// + /// \brief error - Error handler class. + /// + QCryptoError error; + }; +} // namespace QSimpleCrypto + +#endif // QBLOCKCIPHER_H diff --git a/client/3rd/QSimpleCrypto/include/QCryptoError.h b/client/3rd/QSimpleCrypto/include/QCryptoError.h new file mode 100644 index 000000000..fc0596545 --- /dev/null +++ b/client/3rd/QSimpleCrypto/include/QCryptoError.h @@ -0,0 +1,45 @@ +#ifndef QCRYPTOERROR_H +#define QCRYPTOERROR_H + +#include + +#include "QSimpleCrypto_global.h" + +/// TODO: Add Special error code for each error. + +// clang-format off +namespace QSimpleCrypto +{ + class QSIMPLECRYPTO_EXPORT QCryptoError : public QObject { + Q_OBJECT + + public: + explicit QCryptoError(QObject* parent = nullptr); + + /// + /// \brief setError - Sets error information + /// \param errorCode - Error code. + /// \param errorSummary - Error summary. + /// + inline void setError(const quint8 errorCode, const QString& errorSummary) + { + m_currentErrorCode = errorCode; + m_errorSummary = errorSummary; + } + + /// + /// \brief lastError - Returns last error. + /// \return Returns eror ID and error Text. + /// + inline QPair lastError() const + { + return QPair(m_currentErrorCode, m_errorSummary); + } + + private: + quint8 m_currentErrorCode; + QString m_errorSummary; + }; +} + +#endif // QCRYPTOERROR_H diff --git a/client/3rd/QSimpleCrypto/include/QRsa.h b/client/3rd/QSimpleCrypto/include/QRsa.h new file mode 100644 index 000000000..45eb31693 --- /dev/null +++ b/client/3rd/QSimpleCrypto/include/QRsa.h @@ -0,0 +1,104 @@ +/** + * Copyright 2021 BrutalWizard (https://github.com/bru74lw1z4rd). All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution +**/ + +#ifndef QRSA_H +#define QRSA_H + +#include "QSimpleCrypto_global.h" + +#include +#include + +#include + +#include +#include +#include + +#include "QCryptoError.h" + +// clang-format off +namespace QSimpleCrypto +{ + class QSIMPLECRYPTO_EXPORT QRsa { + + #define PublicEncrypt 0 + #define PrivateEncrypt 1 + #define PublicDecrypt 2 + #define PrivateDecrypt 3 + + public: + QRsa(); + + /// + /// \brief generateRsaKeys - Function generate Rsa Keys and returns them in OpenSSL structure. + /// \param bits - RSA key size. + /// \param rsaBigNumber - The exponent is an odd number, typically 3, 17 or 65537. + /// \return Returns 'OpenSSL RSA structure' or 'nullptr', if error happened. Returned value must be cleaned up with 'RSA_free()' to avoid memory leak. + /// + RSA* generateRsaKeys(const int& bits, const int& rsaBigNumber); + + /// + /// \brief savePublicKey - Saves to file RSA public key. + /// \param rsa - OpenSSL RSA structure. + /// \param publicKeyFileName - Public key file name. + /// + void savePublicKey(RSA *rsa, const QByteArray& publicKeyFileName); + + /// + /// \brief savePrivateKey - Saves to file RSA private key. + /// \param rsa - OpenSSL RSA structure. + /// \param privateKeyFileName - Private key file name. + /// \param password - Private key password. + /// \param cipher - Can be used with 'OpenSSL EVP_CIPHER' (ecb, cbc, cfb, ofb, ctr) - 128, 192, 256. Example: EVP_aes_256_cbc(). + /// + void savePrivateKey(RSA* rsa, const QByteArray& privateKeyFileName, QByteArray password = "", const EVP_CIPHER* cipher = nullptr); + + /// + /// \brief getPublicKeyFromFile - Gets RSA public key from a file. + /// \param filePath - File path to public key file. + /// \return Returns 'OpenSSL EVP_PKEY structure' or 'nullptr', if error happened. Returned value must be cleaned up with 'EVP_PKEY_free()' to avoid memory leak. + /// + EVP_PKEY* getPublicKeyFromFile(const QByteArray& filePath); + + /// + /// \brief getPrivateKeyFromFile - Gets RSA private key from a file. + /// \param filePath - File path to private key file. + /// \param password - Private key password. + /// \return - Returns 'OpenSSL EVP_PKEY structure' or 'nullptr', if error happened. Returned value must be cleaned up with 'EVP_PKEY_free()' to avoid memory leak. + /// + EVP_PKEY* getPrivateKeyFromFile(const QByteArray& filePath, const QByteArray& password = ""); + + /// + /// \brief encrypt - Encrypt data with RSA algorithm. + /// \param plaintext - Text that must be encrypted. + /// \param rsa - OpenSSL RSA structure. + /// \param encryptType - Public or private encrypt type. (PUBLIC_ENCRYPT, PRIVATE_ENCRYPT). + /// \param padding - OpenSSL RSA padding can be used with: 'RSA_PKCS1_PADDING', 'RSA_NO_PADDING' and etc. + /// \return Returns encrypted data or "", if error happened. + /// + QByteArray encrypt(QByteArray plainText, RSA* rsa, const int& encryptType = PublicEncrypt, const int& padding = RSA_PKCS1_PADDING); + + /// + /// \brief decrypt - Decrypt data with RSA algorithm. + /// \param cipherText - Text that must be decrypted. + /// \param rsa - OpenSSL RSA structure. + /// \param decryptType - Public or private type. (PUBLIC_DECRYPT, PRIVATE_DECRYPT). + /// \param padding - RSA padding can be used with: 'RSA_PKCS1_PADDING', 'RSA_NO_PADDING' and etc. + /// \return - Returns decrypted data or "", if error happened. + /// + QByteArray decrypt(QByteArray cipherText, RSA* rsa, const int& decryptType = PrivateDecrypt, const int& padding = RSA_PKCS1_PADDING); + + /// + /// \brief error - Error handler class. + /// + QCryptoError error; + }; +} // namespace QSimpleCrypto + +#endif // QRSA_H diff --git a/client/3rd/QSimpleCrypto/include/QSimpleCrypto_global.h b/client/3rd/QSimpleCrypto/include/QSimpleCrypto_global.h new file mode 100644 index 000000000..fdd6c020b --- /dev/null +++ b/client/3rd/QSimpleCrypto/include/QSimpleCrypto_global.h @@ -0,0 +1,9 @@ +#ifndef QSIMPLECRYPTO_GLOBAL_H +#define QSIMPLECRYPTO_GLOBAL_H + +#include +#include + +#define QSIMPLECRYPTO_EXPORT + +#endif // QSIMPLECRYPTO_GLOBAL_H diff --git a/client/3rd/QSimpleCrypto/include/QX509.h b/client/3rd/QSimpleCrypto/include/QX509.h new file mode 100644 index 000000000..96e0c76cb --- /dev/null +++ b/client/3rd/QSimpleCrypto/include/QX509.h @@ -0,0 +1,87 @@ +/** + * Copyright 2021 BrutalWizard (https://github.com/bru74lw1z4rd). All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution +**/ + +#ifndef QX509_H +#define QX509_H + +#include "QSimpleCrypto_global.h" + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "QCryptoError.h" + +// clang-format off +namespace QSimpleCrypto +{ + class QSIMPLECRYPTO_EXPORT QX509 { + + #define oneYear 31536000L + #define x509LastVersion 2 + + public: + QX509(); + + /// + /// \brief loadCertificateFromFile - Function load X509 from file and returns OpenSSL structure. + /// \param fileName - File path to certificate. + /// \return Returns OpenSSL X509 structure or nullptr, if error happened. Returned value must be cleaned up with 'X509_free' to avoid memory leak. + /// + X509* loadCertificateFromFile(const QByteArray& fileName); + + /// + /// \brief signCertificate - Function signs X509 certificate and returns signed X509 OpenSSL structure. + /// \param endCertificate - Certificate that will be signed + /// \param caCertificate - CA certificate that will sign end certificate + /// \param caPrivateKey - CA certificate private key + /// \param fileName - With that name certificate will be saved. Leave "", if don't need to save it + /// \return Returns OpenSSL X509 structure or nullptr, if error happened. + /// + X509* signCertificate(X509* endCertificate, X509* caCertificate, EVP_PKEY* caPrivateKey, const QByteArray& fileName = ""); + + /// + /// \brief verifyCertificate - Function verifies X509 certificate and returns verified X509 OpenSSL structure. + /// \param x509 - OpenSSL X509. That certificate will be verified. + /// \param store - Trusted certificate must be added to X509_Store with 'addCertificateToStore(X509_STORE* ctx, X509* x509)'. + /// \return Returns OpenSSL X509 structure or nullptr, if error happened + /// + X509* verifyCertificate(X509* x509, X509_STORE* store); + + /// + /// \brief generateSelfSignedCertificate - Function generatesand returns self signed X509. + /// \param rsa - OpenSSL RSA. + /// \param additionalData - Certificate information. + /// \param certificateFileName - With that name certificate will be saved. Leave "", if don't need to save it. + /// \param md - OpenSSL EVP_MD structure. Example: EVP_sha512(). + /// \param serialNumber - X509 certificate serial number. + /// \param version - X509 certificate version. + /// \param notBefore - X509 start date. + /// \param notAfter - X509 end date. + /// \return Returns OpenSSL X509 structure or nullptr, if error happened. Returned value must be cleaned up with 'X509_free' to avoid memory leak. + /// + X509* generateSelfSignedCertificate(const RSA* rsa, const QMap& additionalData, + const QByteArray& certificateFileName = "", const EVP_MD* md = EVP_sha512(), + const long& serialNumber = 1, const long& version = x509LastVersion, + const long& notBefore = 0, const long& notAfter = oneYear); + + /// + /// \brief error - Error handler class. + /// + QCryptoError error; + }; +} // namespace QSimpleCrypto + +#endif // QX509_H diff --git a/client/3rd/QSimpleCrypto/include/QX509Store.h b/client/3rd/QSimpleCrypto/include/QX509Store.h new file mode 100644 index 000000000..8cd8ca82b --- /dev/null +++ b/client/3rd/QSimpleCrypto/include/QX509Store.h @@ -0,0 +1,120 @@ +/** + * Copyright 2021 BrutalWizard (https://github.com/bru74lw1z4rd). All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution +**/ + +#ifndef QX509STORE_H +#define QX509STORE_H + +#include "QSimpleCrypto_global.h" + +#include +#include +#include + +#include + +#include +#include +#include + +#include "QCryptoError.h" + +// clang-format off +namespace QSimpleCrypto +{ + class QSIMPLECRYPTO_EXPORT QX509Store { + public: + QX509Store(); + + /// + /// \brief addCertificateToStore + /// \param store - OpenSSL X509_STORE. + /// \param x509 - OpenSSL X509. + /// \return Returns 'true' on success and 'false', if error happened. + /// + bool addCertificateToStore(X509_STORE* store, X509* x509); + + /// + /// \brief addLookup + /// \param store - OpenSSL X509_STORE. + /// \param method - OpenSSL X509_LOOKUP_METHOD. Example: X509_LOOKUP_file. + /// \return Returns 'true' on success and 'false', if error happened. + /// + bool addLookup(X509_STORE* store, X509_LOOKUP_METHOD* method); + + /// + /// \brief setCertificateDepth + /// \param store - OpenSSL X509_STORE. + /// \param depth - That is the maximum number of untrusted CA certificates that can appear in a chain. Example: 0. + /// \return Returns 'true' on success and 'false', if error happened. + /// + bool setDepth(X509_STORE* store, const int& depth); + + /// + /// \brief setFlag + /// \param store - OpenSSL X509_STORE. + /// \param flag - The verification flags consists of zero or more of the following flags ored together. Example: X509_V_FLAG_CRL_CHECK. + /// \return Returns 'true' on success and 'false', if error happened. + /// + bool setFlag(X509_STORE* store, const unsigned long& flag); + + /// + /// \brief setFlag + /// \param store - OpenSSL X509_STORE. + /// \param purpose - Verification purpose in param to purpose. Example: X509_PURPOSE_ANY. + /// \return Returns 'true' on success and 'false', if error happened. + /// + bool setPurpose(X509_STORE* store, const int& purpose); + + /// + /// \brief setTrust + /// \param store - OpenSSL X509_STORE. + /// \param trust - Trust Level. Example: X509_TRUST_SSL_SERVER. + /// \return Returns 'true' on success and 'false', if error happened. + /// + bool setTrust(X509_STORE* store, const int& trust); + + /// + /// \brief setDefaultPaths + /// \param store - OpenSSL X509_STORE. + /// \return Returns 'true' on success and 'false', if error happened. + /// + bool setDefaultPaths(X509_STORE* store); + + /// + /// \brief loadLocations + /// \param store - OpenSSL X509_STORE. + /// \param fileName - File name. Example: "caCertificate.pem". + /// \param dirPath - Path to file. Example: "path/To/File". + /// \return Returns 'true' on success and 'false', if error happened. + /// + bool loadLocations(X509_STORE* store, const QByteArray& fileName, const QByteArray& dirPath); + + /// + /// \brief loadLocations + /// \param store - OpenSSL X509_STORE. + /// \param file - Qt QFile that will be loaded. + /// \return Returns 'true' on success and 'false', if error happened. + /// + bool loadLocations(X509_STORE* store, const QFile& file); + + /// + /// \brief loadLocations + /// \param store - OpenSSL X509_STORE. + /// \param fileInfo - Qt QFileInfo. + /// \return Returns 'true' on success and 'false', if error happened. + /// + bool loadLocations(X509_STORE* store, const QFileInfo& fileInfo); + + /// + /// \brief error - Error handler class. + /// + QCryptoError error; + }; +} + +#endif // QX509STORE_H diff --git a/client/3rd/QSimpleCrypto/sources/QAead.cpp b/client/3rd/QSimpleCrypto/sources/QAead.cpp new file mode 100644 index 000000000..968c88417 --- /dev/null +++ b/client/3rd/QSimpleCrypto/sources/QAead.cpp @@ -0,0 +1,364 @@ +/** + * Copyright 2021 BrutalWizard (https://github.com/bru74lw1z4rd). All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution +**/ + +#include "include/QAead.h" + +QSimpleCrypto::QAead::QAead() +{ +} + +/// +/// \brief QSimpleCrypto::QAEAD::encryptAesGcm - Function encrypts data with Gcm algorithm. +/// \param data - Data that will be encrypted. +/// \param key - AES key. +/// \param iv - Initialization vector. +/// \param tag - Authorization tag. +/// \param aad - Additional authenticated data. Must be nullptr, if not used. +/// \param cipher - Can be used with OpenSSL EVP_CIPHER (gcm) - 128, 192, 256. Example: EVP_aes_256_gcm(). +/// \return Returns encrypted data or "", if error happened. +/// +QByteArray QSimpleCrypto::QAead::encryptAesGcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad, const EVP_CIPHER* cipher) +{ + try { + /* Initialize EVP_CIPHER_CTX */ + std::unique_ptr encryptionCipher { EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free }; + if (encryptionCipher == nullptr) { + throw std::runtime_error("Couldn't initialize \'encryptionCipher\'. EVP_CIPHER_CTX_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set data length */ + int plainTextLength = data.size(); + int cipherTextLength = 0; + + /* Initialize cipherText. Here encrypted data will be stored */ + std::unique_ptr cipherText { new unsigned char[plainTextLength]() }; + if (cipherText == nullptr) { + throw std::runtime_error("Couldn't allocate memory for 'ciphertext'."); + } + + /* Initialize encryption operation. */ + if (!EVP_EncryptInit_ex(encryptionCipher.get(), cipher, nullptr, reinterpret_cast(key.data()), reinterpret_cast(iv.data()))) { + throw std::runtime_error("Couldn't initialize encryption operation. EVP_EncryptInit_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set IV length if default 12 bytes (96 bits) is not appropriate */ + if (!EVP_CIPHER_CTX_ctrl(encryptionCipher.get(), EVP_CTRL_GCM_SET_IVLEN, iv.length(), nullptr)) { + throw std::runtime_error("Couldn't set IV length. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + +// /* Check if aad need to be used */ +// if (aad.length() > 0) { +// /* Provide any AAD data. This can be called zero or more times as required */ +// if (!EVP_EncryptUpdate(encryptionCipher.get(), nullptr, &cipherTextLength, reinterpret_cast(aad.data()), aad.length())) { +// throw std::runtime_error("Couldn't provide aad data. EVP_EncryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); +// } +// } + + /* + * Provide the message to be encrypted, and obtain the encrypted output. + * EVP_EncryptUpdate can be called multiple times if necessary + */ + if (!EVP_EncryptUpdate(encryptionCipher.get(), cipherText.get(), &cipherTextLength, reinterpret_cast(data.data()), plainTextLength)) { + throw std::runtime_error("Couldn't provide message to be encrypted. EVP_EncryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* + * Finalize the encryption. Normally cipher text bytes may be written at + * this stage, but this does not occur in GCM mode + */ + if (!EVP_EncryptFinal_ex(encryptionCipher.get(), cipherText.get(), &plainTextLength)) { + throw std::runtime_error("Couldn't finalize encryption. EVP_EncryptFinal_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + +// /* Get tag */ +// if (!EVP_CIPHER_CTX_ctrl(encryptionCipher.get(), EVP_CTRL_GCM_GET_TAG, tag->length(), reinterpret_cast(tag->data()))) { +// throw std::runtime_error("Couldn't get tag. EVP_CIPHER_CTX_ctrl(. Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); +// } + + /* Finilize data to be readable with qt */ + QByteArray encryptedData = QByteArray(reinterpret_cast(cipherText.get()), cipherTextLength); + + return encryptedData; + + } catch (std::exception& exception) { + QSimpleCrypto::QAead::error.setError(1, exception.what()); + return QByteArray(); + } catch (...) { + QSimpleCrypto::QAead::error.setError(2, "Unknown error!"); + return QByteArray(); + } + + return QByteArray(); +} + +/// +/// \brief QSimpleCrypto::QAEAD::decryptAesGcm - Function decrypts data with Gcm algorithm. +/// \param data - Data that will be decrypted +/// \param key - AES key +/// \param iv - Initialization vector +/// \param tag - Authorization tag +/// \param aad - Additional authenticated data. Must be nullptr, if not used +/// \param cipher - Can be used with OpenSSL EVP_CIPHER (gcm) - 128, 192, 256. Example: EVP_aes_256_gcm() +/// \return Returns decrypted data or "", if error happened. +/// +QByteArray QSimpleCrypto::QAead::decryptAesGcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad, const EVP_CIPHER* cipher) +{ + try { + /* Initialize EVP_CIPHER_CTX */ + std::unique_ptr decryptionCipher { EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free }; + if (decryptionCipher.get() == nullptr) { + throw std::runtime_error("Couldn't initialize \'decryptionCipher\'. EVP_CIPHER_CTX_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set data length */ + int cipherTextLength = data.size(); + int plainTextLength = 0; + + /* Initialize plainText. Here decrypted data will be stored */ + std::unique_ptr plainText { new unsigned char[cipherTextLength]() }; + if (plainText == nullptr) { + throw std::runtime_error("Couldn't allocate memory for 'plaintext'."); + } + + /* Initialize decryption operation. */ + if (!EVP_DecryptInit_ex(decryptionCipher.get(), cipher, nullptr, reinterpret_cast(key.data()), reinterpret_cast(iv.data()))) { + throw std::runtime_error("Couldn't initialize decryption operation. EVP_DecryptInit_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set IV length. Not necessary if this is 12 bytes (96 bits) */ + if (!EVP_CIPHER_CTX_ctrl(decryptionCipher.get(), EVP_CTRL_GCM_SET_IVLEN, iv.length(), nullptr)) { + throw std::runtime_error("Couldn't set IV length. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + +// /* Check if aad need to be used */ +// if (aad.length() > 0) { +// /* Provide any AAD data. This can be called zero or more times as required */ +// if (!EVP_DecryptUpdate(decryptionCipher.get(), nullptr, &plainTextLength, reinterpret_cast(aad.data()), aad.length())) { +// throw std::runtime_error("Couldn't provide aad data. EVP_DecryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); +// } +// } + + /* + * Provide the message to be decrypted, and obtain the plain text output. + * EVP_DecryptUpdate can be called multiple times if necessary + */ + if (!EVP_DecryptUpdate(decryptionCipher.get(), plainText.get(), &plainTextLength, reinterpret_cast(data.data()), cipherTextLength)) { + throw std::runtime_error("Couldn't provide message to be decrypted. EVP_DecryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + +// /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ +// if (!EVP_CIPHER_CTX_ctrl(decryptionCipher.get(), EVP_CTRL_GCM_SET_TAG, tag->length(), reinterpret_cast(tag->data()))) { +// throw std::runtime_error("Coldn't set tag. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); +// } + + /* + * Finalize the decryption. A positive return value indicates success, + * anything else is a failure - the plain text is not trustworthy. + */ + if (!EVP_DecryptFinal_ex(decryptionCipher.get(), plainText.get(), &cipherTextLength)) { + throw std::runtime_error("Couldn't finalize decryption. EVP_DecryptFinal_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Finilize data to be readable with qt */ + QByteArray decryptedData = QByteArray(reinterpret_cast(plainText.get()), plainTextLength); + + return decryptedData; + + } catch (std::exception& exception) { + QSimpleCrypto::QAead::error.setError(1, exception.what()); + return QByteArray(); + } catch (...) { + QSimpleCrypto::QAead::error.setError(2, "Unknown error!"); + return QByteArray(); + } + + return QByteArray(); +} + +/// +/// \brief QSimpleCrypto::QAEAD::encryptAesCcm - Function encrypts data with Ccm algorithm. +/// \param data - Data that will be encrypted. +/// \param key - AES key. +/// \param iv - Initialization vector. +/// \param tag - Authorization tag. +/// \param aad - Additional authenticated data. Must be nullptr, if not used. +/// \param cipher - Can be used with OpenSSL EVP_CIPHER (ccm) - 128, 192, 256. Example: EVP_aes_256_ccm(). +/// \return Returns encrypted data or "", if error happened. +/// +QByteArray QSimpleCrypto::QAead::encryptAesCcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad, const EVP_CIPHER* cipher) +{ + try { + /* Initialize EVP_CIPHER_CTX */ + std::unique_ptr encryptionCipher { EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free }; + if (encryptionCipher == nullptr) { + throw std::runtime_error("Couldn't initialize \'encryptionCipher\'. EVP_CIPHER_CTX_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set data length */ + int plainTextLength = data.size(); + int cipherTextLength = 0; + + /* Initialize cipherText. Here encrypted data will be stored */ + std::unique_ptr cipherText { new unsigned char[plainTextLength]() }; + if (cipherText.get() == nullptr) { + throw std::runtime_error("Couldn't allocate memory for 'ciphertext'."); + } + + /* Initialize encryption operation. */ + if (!EVP_EncryptInit_ex(encryptionCipher.get(), cipher, nullptr, reinterpret_cast(key.data()), reinterpret_cast(iv.data()))) { + throw std::runtime_error("Couldn't initialize encryption operation. EVP_EncryptInit_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set IV length if default 12 bytes (96 bits) is not appropriate */ + if (!EVP_CIPHER_CTX_ctrl(encryptionCipher.get(), EVP_CTRL_CCM_SET_IVLEN, iv.length(), nullptr)) { + throw std::runtime_error("Couldn't set IV length. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set tag length */ + if (!EVP_CIPHER_CTX_ctrl(encryptionCipher.get(), EVP_CTRL_CCM_SET_TAG, tag->length(), nullptr)) { + throw std::runtime_error("Coldn't set tag. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Check if aad need to be used */ + if (aad.length() > 0) { + /* Provide the total plain text length */ + if (!EVP_EncryptUpdate(encryptionCipher.get(), nullptr, &cipherTextLength, nullptr, plainTextLength)) { + throw std::runtime_error("Couldn't provide total plaintext length. EVP_EncryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Provide any AAD data. This can be called zero or more times as required */ + if (!EVP_EncryptUpdate(encryptionCipher.get(), nullptr, &cipherTextLength, reinterpret_cast(aad.data()), aad.length())) { + throw std::runtime_error("Couldn't provide aad data. EVP_EncryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + } + + /* + * Provide the message to be encrypted, and obtain the encrypted output. + * EVP_EncryptUpdate can be called multiple times if necessary + */ + if (!EVP_EncryptUpdate(encryptionCipher.get(), cipherText.get(), &cipherTextLength, reinterpret_cast(data.data()), plainTextLength)) { + throw std::runtime_error("Couldn't provide message to be encrypted. EVP_EncryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* + * Finalize the encryption. Normally ciphertext bytes may be written at + * this stage, but this does not occur in GCM mode + */ + if (!EVP_EncryptFinal_ex(encryptionCipher.get(), cipherText.get(), &plainTextLength)) { + throw std::runtime_error("Couldn't finalize encryption. EVP_EncryptFinal_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Get tag */ + if (!EVP_CIPHER_CTX_ctrl(encryptionCipher.get(), EVP_CTRL_CCM_GET_TAG, tag->length(), reinterpret_cast(tag->data()))) { + throw std::runtime_error("Couldn't get tag. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Finilize data to be readable with qt */ + QByteArray encryptedData = QByteArray(reinterpret_cast(cipherText.get()), cipherTextLength); + + return encryptedData; + + } catch (std::exception& exception) { + QSimpleCrypto::QAead::error.setError(1, exception.what()); + return QByteArray(); + } catch (...) { + QSimpleCrypto::QAead::error.setError(2, "Unknown error!"); + return QByteArray(); + } + + return QByteArray(); +} + +/// +/// \brief QSimpleCrypto::QAEAD::decryptAesCcm - Function decrypts data with Ccm algorithm. +/// \param data - Data that will be decrypted. +/// \param key - AES key. +/// \param iv - Initialization vector. +/// \param tag - Authorization tag. +/// \param aad - Additional authenticated data. Must be nullptr, if not used. +/// \param cipher - Can be used with OpenSSL EVP_CIPHER (ccm) - 128, 192, 256. Example: EVP_aes_256_ccm(). +/// \return Returns decrypted data or "", if error happened. +/// +QByteArray QSimpleCrypto::QAead::decryptAesCcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad, const EVP_CIPHER* cipher) +{ + try { + /* Initialize EVP_CIPHER_CTX */ + std::unique_ptr decryptionCipher { EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free }; + if (decryptionCipher.get() == nullptr) { + throw std::runtime_error("Couldn't initialize \'decryptionCipher\'. EVP_CIPHER_CTX_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set data length */ + int cipherTextLength = data.size(); + int plainTextLength = 0; + + /* Initialize plainText. Here decrypted data will be stored */ + std::unique_ptr plainText { new unsigned char[cipherTextLength]() }; + if (plainText == nullptr) { + throw std::runtime_error("Couldn't allocate memory for 'plaintext'."); + } + + /* Initialize decryption operation. */ + if (!EVP_DecryptInit_ex(decryptionCipher.get(), cipher, nullptr, reinterpret_cast(key.data()), reinterpret_cast(iv.data()))) { + throw std::runtime_error("Couldn't initialize decryption operation. EVP_DecryptInit_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set IV length. Not necessary if this is 12 bytes (96 bits) */ + if (!EVP_CIPHER_CTX_ctrl(decryptionCipher.get(), EVP_CTRL_CCM_SET_IVLEN, iv.length(), nullptr)) { + throw std::runtime_error("Couldn't set IV length. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ + if (!EVP_CIPHER_CTX_ctrl(decryptionCipher.get(), EVP_CTRL_CCM_SET_TAG, tag->length(), reinterpret_cast(tag->data()))) { + throw std::runtime_error("Coldn't set tag. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Check if aad need to be used */ + if (aad.length() > 0) { + /* Provide the total ciphertext length */ + if (!EVP_DecryptUpdate(decryptionCipher.get(), nullptr, &plainTextLength, nullptr, cipherTextLength)) { + throw std::runtime_error("Couldn't provide total plaintext length. EVP_DecryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Provide any AAD data. This can be called zero or more times as required */ + if (!EVP_DecryptUpdate(decryptionCipher.get(), nullptr, &plainTextLength, reinterpret_cast(aad.data()), aad.length())) { + throw std::runtime_error("Couldn't provide aad data. EVP_DecryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + } + + /* + * Provide the message to be decrypted, and obtain the plaintext output. + * EVP_DecryptUpdate can be called multiple times if necessary + */ + if (!EVP_DecryptUpdate(decryptionCipher.get(), plainText.get(), &plainTextLength, reinterpret_cast(data.data()), cipherTextLength)) { + throw std::runtime_error("Couldn't provide message to be decrypted. EVP_DecryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* + * Finalize the decryption. A positive return value indicates success, + * anything else is a failure - the plaintext is not trustworthy. + */ + if (!EVP_DecryptFinal_ex(decryptionCipher.get(), plainText.get(), &cipherTextLength)) { + throw std::runtime_error("Couldn't finalize decryption. EVP_DecryptFinal_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Finilize data to be readable with qt */ + QByteArray decryptedData = QByteArray(reinterpret_cast(plainText.get()), plainTextLength); + + return decryptedData; + + } catch (std::exception& exception) { + QSimpleCrypto::QAead::error.setError(1, exception.what()); + return QByteArray(); + } catch (...) { + QSimpleCrypto::QAead::error.setError(2, "Unknown error!"); + return QByteArray(); + } + + return QByteArray(); +} diff --git a/client/3rd/QSimpleCrypto/sources/QBlockCipher.cpp b/client/3rd/QSimpleCrypto/sources/QBlockCipher.cpp new file mode 100644 index 000000000..c01b9a2f8 --- /dev/null +++ b/client/3rd/QSimpleCrypto/sources/QBlockCipher.cpp @@ -0,0 +1,184 @@ +/** + * Copyright 2021 BrutalWizard (https://github.com/bru74lw1z4rd). All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution +**/ + +#include "include/QBlockCipher.h" + +QSimpleCrypto::QBlockCipher::QBlockCipher() +{ +} + +/// +/// \brief QSimpleCrypto::QBlockCipher::generateRandomBytes - Function generates random bytes by size. +/// \param size - Size of generated bytes. +/// \return Returns random bytes. +/// +QByteArray QSimpleCrypto::QBlockCipher::generateRandomBytes(const int& size) +{ + unsigned char arr[sizeof(size)]; + RAND_bytes(arr, sizeof(size)); + + QByteArray buffer = QByteArray(reinterpret_cast(arr), size); + return buffer; +} + +/// +/// \brief QSimpleCrypto::QBlockCipher::encryptAesBlockCipher - Function encrypts data with Aes Block Cipher algorithm. +/// \param data - Data that will be encrypted. +/// \param key - AES key. +/// \param iv - Initialization vector. +/// \param password - Encryption password. +/// \param salt - Random delta. +/// \param rounds - Transformation rounds. +/// \param chiper - Can be used with OpenSSL EVP_CIPHER (ecb, cbc, cfb, ofb, ctr) - 128, 192, 256. Example: EVP_aes_256_cbc(). +/// \param md - Hash algroitm (OpenSSL EVP_MD). Example: EVP_sha512(). +/// \return Returns decrypted data or "", if error happened. +/// +QByteArray QSimpleCrypto::QBlockCipher::encryptAesBlockCipher(QByteArray data, QByteArray key, + QByteArray iv, + const int& rounds, const EVP_CIPHER* cipher, const EVP_MD* md) +{ + try { + /* Initialize EVP_CIPHER_CTX */ + std::unique_ptr encryptionCipher { EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free }; + if (encryptionCipher == nullptr) { + throw std::runtime_error("Couldn't initialize \'encryptionCipher\'. EVP_CIPHER_CTX_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Reinterpret values for multi use */ + unsigned char* m_key = reinterpret_cast(key.data()); + unsigned char* m_iv = reinterpret_cast(iv.data()); + + /* Set data length */ + int cipherTextLength(data.size() + AES_BLOCK_SIZE); + int finalLength = 0; + + /* Initialize cipcherText. Here encrypted data will be stored */ + std::unique_ptr cipherText { new unsigned char[cipherTextLength]() }; + if (cipherText == nullptr) { + throw std::runtime_error("Couldn't allocate memory for 'cipherText'."); + } + + // Bug here +// /* Start encryption with password based encryption routine */ +// if (!EVP_BytesToKey(cipher, md, reinterpret_cast(salt.data()), reinterpret_cast(password.data()), password.length(), rounds, m_key, m_iv)) { +// throw std::runtime_error("Couldn't start encryption routine. EVP_BytesToKey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); +// } + + /* Initialize encryption operation. */ + if (!EVP_EncryptInit_ex(encryptionCipher.get(), cipher, nullptr, m_key, m_iv)) { + throw std::runtime_error("Couldn't initialize encryption operation. EVP_EncryptInit_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* + * Provide the message to be encrypted, and obtain the encrypted output. + * EVP_EncryptUpdate can be called multiple times if necessary + */ + if (!EVP_EncryptUpdate(encryptionCipher.get(), cipherText.get(), &cipherTextLength, reinterpret_cast(data.data()), data.size())) { + throw std::runtime_error("Couldn't provide message to be encrypted. EVP_EncryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Finalize the encryption. Normally ciphertext bytes may be written at this stage */ + if (!EVP_EncryptFinal(encryptionCipher.get(), cipherText.get() + cipherTextLength, &finalLength)) { + throw std::runtime_error("Couldn't finalize encryption. EVP_EncryptFinal(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Finilize data to be readable with qt */ + QByteArray encryptedData = QByteArray(reinterpret_cast(cipherText.get()), cipherTextLength + finalLength); + + return encryptedData; + + } catch (std::exception& exception) { + QSimpleCrypto::QBlockCipher::error.setError(1, exception.what()); + return QByteArray(); + } catch (...) { + QSimpleCrypto::QBlockCipher::error.setError(2, "Unknown error!"); + return QByteArray(); + } + + return QByteArray(); +} + +/// +/// \brief QSimpleCrypto::QBlockCipher::encryptAesBlockCipher - Function decrypts data with Aes Block Cipher algorithm. +/// \param data - Data that will be decrypted. +/// \param key - AES key. +/// \param iv - Initialization vector. +/// \param password - Decryption password. +/// \param salt - Random delta. +/// \param rounds - Transformation rounds. +/// \param chiper - Can be used with OpenSSL EVP_CIPHER (ecb, cbc, cfb, ofb, ctr) - 128, 192, 256. Example: EVP_aes_256_cbc(). +/// \param md - Hash algroitm (OpenSSL EVP_MD). Example: EVP_sha512(). +/// \return Returns decrypted data or "", if error happened. +/// +QByteArray QSimpleCrypto::QBlockCipher::decryptAesBlockCipher(QByteArray data, QByteArray key, + QByteArray iv, + const int& rounds, const EVP_CIPHER* cipher, const EVP_MD* md) +{ + try { + /* Initialize EVP_CIPHER_CTX */ + std::unique_ptr decryptionCipher { EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free }; + if (decryptionCipher == nullptr) { + throw std::runtime_error("Couldn't initialize \'decryptionCipher\'. EVP_CIPHER_CTX_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Reinterpret values for multi use */ + unsigned char* m_key = reinterpret_cast(key.data()); + unsigned char* m_iv = reinterpret_cast(iv.data()); + + /* Set data length */ + int plainTextLength(data.size()); + int finalLength = 0; + + /* Initialize plainText. Here decrypted data will be stored */ + std::unique_ptr plainText { new unsigned char[plainTextLength + AES_BLOCK_SIZE]() }; + if (plainText == nullptr) { + throw std::runtime_error("Couldn't allocate memory for \'plainText\'. EVP_CIPHER_CTX_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + // Bug here +// /* Start encryption with password based encryption routine */ +// if (!EVP_BytesToKey(cipher, md, reinterpret_cast(salt.data()), reinterpret_cast(password.data()), password.length(), rounds, m_key, m_iv)) { +// throw std::runtime_error("Couldn't start decryption routine. EVP_BytesToKey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); +// } + + /* Initialize decryption operation. */ + if (!EVP_DecryptInit_ex(decryptionCipher.get(), cipher, nullptr, m_key, m_iv)) { + throw std::runtime_error("Couldn't initialize decryption operation. EVP_DecryptInit_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* + * Provide the message to be decrypted, and obtain the plaintext output. + * EVP_DecryptUpdate can be called multiple times if necessary + */ + if (!EVP_DecryptUpdate(decryptionCipher.get(), plainText.get(), &plainTextLength, reinterpret_cast(data.data()), data.size())) { + throw std::runtime_error("Couldn't provide message to be decrypted. EVP_DecryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* + * Finalize the decryption. A positive return value indicates success, + * anything else is a failure - the plaintext is not trustworthy. + */ + if (!EVP_DecryptFinal(decryptionCipher.get(), plainText.get() + plainTextLength, &finalLength)) { + throw std::runtime_error("Couldn't finalize decryption. EVP_DecryptFinal. Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Finilize data to be readable with qt */ + QByteArray decryptedData = QByteArray(reinterpret_cast(plainText.get()), plainTextLength + finalLength); + + return decryptedData; + + } catch (std::exception& exception) { + QSimpleCrypto::QBlockCipher::error.setError(1, exception.what()); + return QByteArray(exception.what()); + } catch (...) { + QSimpleCrypto::QBlockCipher::error.setError(2, "Unknown error!"); + return QByteArray(); + } + + return QByteArray(); +} diff --git a/client/3rd/QSimpleCrypto/sources/QCryptoError.cpp b/client/3rd/QSimpleCrypto/sources/QCryptoError.cpp new file mode 100644 index 000000000..234f55d73 --- /dev/null +++ b/client/3rd/QSimpleCrypto/sources/QCryptoError.cpp @@ -0,0 +1,6 @@ +#include "include/QCryptoError.h" + +QSimpleCrypto::QCryptoError::QCryptoError(QObject* parent) + : QObject(parent) +{ +} diff --git a/client/3rd/QSimpleCrypto/sources/QRsa.cpp b/client/3rd/QSimpleCrypto/sources/QRsa.cpp new file mode 100644 index 000000000..544d67464 --- /dev/null +++ b/client/3rd/QSimpleCrypto/sources/QRsa.cpp @@ -0,0 +1,274 @@ +/** + * Copyright 2021 BrutalWizard (https://github.com/bru74lw1z4rd). All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution +**/ + +#include "include/QRsa.h" + +QSimpleCrypto::QRsa::QRsa() +{ +} + +/// +/// \brief QSimpleCrypto::QRSA::generateRsaKeys - Function generate Rsa Keys and returns them in OpenSSL structure. +/// \param bits - RSA key size. +/// \param rsaBigNumber - The exponent is an odd number, typically 3, 17 or 65537. +/// \return Returns 'OpenSSL RSA structure' or 'nullptr', if error happened. Returned value must be cleaned up with 'RSA_free()' to avoid memory leak. +/// +RSA* QSimpleCrypto::QRsa::generateRsaKeys(const int& bits, const int& rsaBigNumber) +{ + try { + /* Initialize big number */ + std::unique_ptr bigNumber { BN_new(), BN_free }; + if (bigNumber == nullptr) { + throw std::runtime_error("Couldn't initialize \'bigNumber\'. BN_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + return nullptr; + } + + /* Set big number */ + if (!BN_set_word(bigNumber.get(), rsaBigNumber)) { + throw std::runtime_error("Couldn't set bigNumber. BN_set_word(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Initialize RSA */ + RSA* rsa = nullptr; + if (!(rsa = RSA_new())) { + throw std::runtime_error("Couldn't initialize x509. X509_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Generate key pair and store it in RSA */ + if (!RSA_generate_key_ex(rsa, bits, bigNumber.get(), nullptr)) { + throw std::runtime_error("Couldn't generate RSA. RSA_generate_key_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + return rsa; + } catch (std::exception& exception) { + QSimpleCrypto::QRsa::error.setError(1, exception.what()); + return nullptr; + } catch (...) { + QSimpleCrypto::QRsa::error.setError(2, "Unknown error!"); + return nullptr; + } +} + +/// +/// \brief QSimpleCrypto::QRSA::savePublicKey - Saves to file RSA public key. +/// \param rsa - OpenSSL RSA structure. +/// \param publicKeyFileName - Public key file name. +/// +void QSimpleCrypto::QRsa::savePublicKey(RSA* rsa, const QByteArray& publicKeyFileName) +{ + try { + /* Initialize BIO */ + std::unique_ptr bioPublicKey { BIO_new_file(publicKeyFileName.data(), "w+"), BIO_free_all }; + if (bioPublicKey == nullptr) { + throw std::runtime_error("Couldn't initialize \'bioPublicKey\'. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Write public key on file */ + if (!PEM_write_bio_RSA_PUBKEY(bioPublicKey.get(), rsa)) { + throw std::runtime_error("Couldn't save public key. PEM_write_bio_RSAPublicKey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + } catch (std::exception& exception) { + QSimpleCrypto::QRsa::error.setError(1, exception.what()); + return; + } catch (...) { + QSimpleCrypto::QRsa::error.setError(2, "Unknown error!"); + return; + } +} + +/// +/// \brief QSimpleCrypto::QRSA::savePrivateKey - Saves to file RSA private key. +/// \param rsa - OpenSSL RSA structure. +/// \param privateKeyFileName - Private key file name. +/// \param password - Private key password. +/// \param cipher - Can be used with 'OpenSSL EVP_CIPHER' (ecb, cbc, cfb, ofb, ctr) - 128, 192, 256. Example: EVP_aes_256_cbc(). +/// +void QSimpleCrypto::QRsa::savePrivateKey(RSA* rsa, const QByteArray& privateKeyFileName, QByteArray password, const EVP_CIPHER* cipher) +{ + try { + /* Initialize BIO */ + std::unique_ptr bioPrivateKey { BIO_new_file(privateKeyFileName.data(), "w+"), BIO_free_all }; + if (bioPrivateKey == nullptr) { + throw std::runtime_error("Couldn't initialize bioPrivateKey. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Write private key to file */ + if (!PEM_write_bio_RSAPrivateKey(bioPrivateKey.get(), rsa, cipher, reinterpret_cast(password.data()), password.size(), nullptr, nullptr)) { + throw std::runtime_error("Couldn't save private key. PEM_write_bio_RSAPrivateKey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + } catch (std::exception& exception) { + QSimpleCrypto::QRsa::error.setError(1, exception.what()); + return; + } catch (...) { + QSimpleCrypto::QRsa::error.setError(2, "Unknown error!"); + return; + } +} + +/// +/// \brief QSimpleCrypto::QRSA::getPublicKeyFromFile - Gets RSA public key from a file. +/// \param filePath - File path to public key file. +/// \return Returns 'OpenSSL EVP_PKEY structure' or 'nullptr', if error happened. Returned value must be cleaned up with 'EVP_PKEY_free()' to avoid memory leak. +/// +EVP_PKEY* QSimpleCrypto::QRsa::getPublicKeyFromFile(const QByteArray& filePath) +{ + try { + /* Initialize BIO */ + std::unique_ptr bioPublicKey { BIO_new_file(filePath.data(), "r"), BIO_free_all }; + if (bioPublicKey == nullptr) { + throw std::runtime_error("Couldn't initialize bioPublicKey. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Initialize EVP_PKEY */ + EVP_PKEY* keyStore = nullptr; + if (!(keyStore = EVP_PKEY_new())) { + throw std::runtime_error("Couldn't initialize keyStore. EVP_PKEY_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Write private key to file */ + if (!PEM_read_bio_PUBKEY(bioPublicKey.get(), &keyStore, nullptr, nullptr)) { + throw std::runtime_error("Couldn't read private key. PEM_read_bio_PrivateKey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + return keyStore; + + } catch (std::exception& exception) { + QSimpleCrypto::QRsa::error.setError(1, exception.what()); + return nullptr; + } catch (...) { + QSimpleCrypto::QRsa::error.setError(2, "Unknown error!"); + return nullptr; + } +} + +/// +/// \brief QSimpleCrypto::QRSA::getPrivateKeyFromFile - Gets RSA private key from a file. +/// \param filePath - File path to private key file. +/// \param password - Private key password. +/// \return - Returns 'OpenSSL EVP_PKEY structure' or 'nullptr', if error happened. Returned value must be cleaned up with 'EVP_PKEY_free()' to avoid memory leak. +/// +EVP_PKEY* QSimpleCrypto::QRsa::getPrivateKeyFromFile(const QByteArray& filePath, const QByteArray& password) +{ + try { + /* Initialize BIO */ + std::unique_ptr bioPrivateKey { BIO_new_file(filePath.data(), "r"), BIO_free_all }; + if (bioPrivateKey == nullptr) { + throw std::runtime_error("Couldn't initialize bioPrivateKey. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Initialize EVP_PKEY */ + EVP_PKEY* keyStore = nullptr; + if (!(keyStore = EVP_PKEY_new())) { + throw std::runtime_error("Couldn't initialize keyStore. EVP_PKEY_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Write private key to file */ + if (!PEM_read_bio_PrivateKey(bioPrivateKey.get(), &keyStore, nullptr, (void*)password.data())) { + throw std::runtime_error("Couldn't read private key. PEM_read_bio_PrivateKey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + return keyStore; + + } catch (std::exception& exception) { + QSimpleCrypto::QRsa::error.setError(1, exception.what()); + return nullptr; + } catch (...) { + QSimpleCrypto::QRsa::error.setError(2, "Unknown error!"); + return nullptr; + } +} + +/// +/// \brief QSimpleCrypto::QRSA::encrypt - Encrypt data with RSA algorithm. +/// \param plaintext - Text that must be encrypted. +/// \param rsa - OpenSSL RSA structure. +/// \param encryptType - Public or private encrypt type. (PUBLIC_ENCRYPT, PRIVATE_ENCRYPT). +/// \param padding - OpenSSL RSA padding can be used with: 'RSA_PKCS1_PADDING', 'RSA_NO_PADDING' and etc. +/// \return Returns encrypted data or "", if error happened. +/// +QByteArray QSimpleCrypto::QRsa::encrypt(QByteArray plainText, RSA* rsa, const int& encryptType, const int& padding) +{ + try { + /* Initialize array. Here encrypted data will be saved */ + std::unique_ptr cipherText { new unsigned char[RSA_size(rsa)]() }; + if (cipherText == nullptr) { + throw std::runtime_error("Couldn't allocate memory for 'cipherText'."); + } + + /* Result of encryption operation */ + short int result = 0; + + /* Execute encryption operation */ + if (encryptType == PublicDecrypt) { + result = RSA_public_encrypt(plainText.size(), reinterpret_cast(plainText.data()), cipherText.get(), rsa, padding); + } else if (encryptType == PrivateDecrypt) { + result = RSA_private_encrypt(plainText.size(), reinterpret_cast(plainText.data()), cipherText.get(), rsa, padding); + } + + /* Check for result */ + if (result <= -1) { + throw std::runtime_error("Couldn't encrypt data. Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Get encrypted data */ + const QByteArray& encryptedData = QByteArray(reinterpret_cast(cipherText.get()), RSA_size(rsa)); + + return encryptedData; + } catch (std::exception& exception) { + QSimpleCrypto::QRsa::error.setError(1, exception.what()); + return ""; + } catch (...) { + QSimpleCrypto::QRsa::error.setError(2, "Unknown error!"); + return ""; + } +} + +/// +/// \brief QSimpleCrypto::QRSA::decrypt - Decrypt data with RSA algorithm. +/// \param cipherText - Text that must be decrypted. +/// \param rsa - OpenSSL RSA structure. +/// \param decryptType - Public or private type. (PUBLIC_DECRYPT, PRIVATE_DECRYPT). +/// \param padding - RSA padding can be used with: 'RSA_PKCS1_PADDING', 'RSA_NO_PADDING' and etc. +/// \return - Returns decrypted data or "", if error happened. +/// +QByteArray QSimpleCrypto::QRsa::decrypt(QByteArray cipherText, RSA* rsa, const int& decryptType, const int& padding) +{ + try { + /* Initialize array. Here decrypted data will be saved */ + std::unique_ptr plainText { new unsigned char[cipherText.size()]() }; + if (plainText == nullptr) { + throw std::runtime_error("Couldn't allocate memory for 'plainText'."); + } + + /* Result of decryption operation */ + short int result = 0; + + /* Execute decryption operation */ + if (decryptType == PublicDecrypt) { + result = RSA_public_decrypt(RSA_size(rsa), reinterpret_cast(cipherText.data()), plainText.get(), rsa, padding); + } else if (decryptType == PrivateDecrypt) { + result = RSA_private_decrypt(RSA_size(rsa), reinterpret_cast(cipherText.data()), plainText.get(), rsa, padding); + } + + /* Check for result */ + if (result <= -1) { + throw std::runtime_error("Couldn't decrypt data. Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Get decrypted data */ + const QByteArray& decryptedData = QByteArray(reinterpret_cast(plainText.get())); + + return decryptedData; + } catch (std::exception& exception) { + QSimpleCrypto::QRsa::error.setError(1, exception.what()); + return ""; + } catch (...) { + QSimpleCrypto::QRsa::error.setError(2, "Unknown error!"); + return ""; + } +} diff --git a/client/3rd/QSimpleCrypto/sources/QX509.cpp b/client/3rd/QSimpleCrypto/sources/QX509.cpp new file mode 100644 index 000000000..8666347db --- /dev/null +++ b/client/3rd/QSimpleCrypto/sources/QX509.cpp @@ -0,0 +1,234 @@ +/** + * Copyright 2021 BrutalWizard (https://github.com/bru74lw1z4rd). All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution +**/ + +#include "include/QX509.h" + +QSimpleCrypto::QX509::QX509() +{ +} + +/// +/// \brief QSimpleCrypto::QX509::loadCertificateFromFile - Function load X509 from file and returns OpenSSL structure. +/// \param fileName - File path to certificate. +/// \return Returns OpenSSL X509 structure or nullptr, if error happened. Returned value must be cleaned up with 'X509_free' to avoid memory leak. +/// +X509* QSimpleCrypto::QX509::loadCertificateFromFile(const QByteArray& fileName) +{ + try { + /* Initialize X509 */ + X509* x509 = nullptr; + if (!(x509 = X509_new())) { + throw std::runtime_error("Couldn't initialize X509. X509_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Initialize BIO */ + std::unique_ptr certFile { BIO_new_file(fileName.data(), "r+"), BIO_free_all }; + if (certFile == nullptr) { + throw std::runtime_error("Couldn't initialize certFile. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Read file */ + if (!PEM_read_bio_X509(certFile.get(), &x509, nullptr, nullptr)) { + throw std::runtime_error("Couldn't read certificate file from disk. PEM_read_bio_X509(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + return x509; + } catch (std::exception& exception) { + QSimpleCrypto::QX509::error.setError(1, exception.what()); + return nullptr; + } catch (...) { + QSimpleCrypto::QX509::error.setError(2, "Unknown error!"); + return nullptr; + } +} + +/// +/// \brief QSimpleCrypto::QX509::signCertificate - Function signs X509 certificate and returns signed X509 OpenSSL structure. +/// \param endCertificate - Certificate that will be signed +/// \param caCertificate - CA certificate that will sign end certificate +/// \param caPrivateKey - CA certificate private key +/// \param fileName - With that name certificate will be saved. Leave "", if don't need to save it +/// \return Returns OpenSSL X509 structure or nullptr, if error happened. +/// +X509* QSimpleCrypto::QX509::signCertificate(X509* endCertificate, X509* caCertificate, EVP_PKEY* caPrivateKey, const QByteArray& fileName) +{ + try { + /* Set issuer to CA's subject. */ + if (!X509_set_issuer_name(endCertificate, X509_get_subject_name(caCertificate))) { + throw std::runtime_error("Couldn't set issuer name for X509. X509_set_issuer_name(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Sign the certificate with key. */ + if (!X509_sign(endCertificate, caPrivateKey, EVP_sha256())) { + throw std::runtime_error("Couldn't sign X509. X509_sign(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Write certificate file on disk. If needed */ + if (!fileName.isEmpty()) { + /* Initialize BIO */ + std::unique_ptr certFile { BIO_new_file(fileName.data(), "w+"), BIO_free_all }; + if (certFile == nullptr) { + throw std::runtime_error("Couldn't initialize certFile. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Write file on disk */ + if (!PEM_write_bio_X509(certFile.get(), endCertificate)) { + throw std::runtime_error("Couldn't write certificate file on disk. PEM_write_bio_X509(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + } + + return endCertificate; + } catch (std::exception& exception) { + QSimpleCrypto::QX509::error.setError(1, exception.what()); + return nullptr; + } catch (...) { + QSimpleCrypto::QX509::error.setError(2, "Unknown error!"); + return nullptr; + } +} + +/// +/// \brief QSimpleCrypto::QX509::verifyCertificate - Function verifies X509 certificate and returns verified X509 OpenSSL structure. +/// \param x509 - OpenSSL X509. That certificate will be verified. +/// \param store - Trusted certificate must be added to X509_Store with 'addCertificateToStore(X509_STORE* ctx, X509* x509)'. +/// \return Returns OpenSSL X509 structure or nullptr, if error happened +/// +X509* QSimpleCrypto::QX509::verifyCertificate(X509* x509, X509_STORE* store) +{ + try { + /* Initialize X509_STORE_CTX */ + std::unique_ptr ctx { X509_STORE_CTX_new(), X509_STORE_CTX_free }; + if (ctx == nullptr) { + throw std::runtime_error("Couldn't initialize keyStore. EVP_PKEY_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set up CTX for a subsequent verification operation */ + if (!X509_STORE_CTX_init(ctx.get(), store, x509, nullptr)) { + throw std::runtime_error("Couldn't initialize X509_STORE_CTX. X509_STORE_CTX_init(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Verify X509 */ + if (!X509_verify_cert(ctx.get())) { + throw std::runtime_error("Couldn't verify cert. X509_verify_cert(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + return x509; + } catch (std::exception& exception) { + QSimpleCrypto::QX509::error.setError(1, exception.what()); + return nullptr; + } catch (...) { + QSimpleCrypto::QX509::error.setError(2, "Unknown error!"); + return nullptr; + } +} + +/// +/// \brief QSimpleCrypto::QX509::generateSelfSignedCertificate - Function generatesand returns self signed X509. +/// \param rsa - OpenSSL RSA. +/// \param additionalData - Certificate information. +/// \param certificateFileName - With that name certificate will be saved. Leave "", if don't need to save it. +/// \param md - OpenSSL EVP_MD structure. Example: EVP_sha512(). +/// \param serialNumber - X509 certificate serial number. +/// \param version - X509 certificate version. +/// \param notBefore - X509 start date. +/// \param notAfter - X509 end date. +/// \return Returns OpenSSL X509 structure or nullptr, if error happened. Returned value must be cleaned up with 'X509_free' to avoid memory leak. +/// +X509* QSimpleCrypto::QX509::generateSelfSignedCertificate(const RSA* rsa, const QMap& additionalData, + const QByteArray& certificateFileName, const EVP_MD* md, + const long& serialNumber, const long& version, + const long& notBefore, const long& notAfter) +{ + try { + /* Initialize X509 */ + X509* x509 = nullptr; + if (!(x509 = X509_new())) { + throw std::runtime_error("Couldn't initialize X509. X509_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Initialize EVP_PKEY */ + std::unique_ptr keyStore { EVP_PKEY_new(), EVP_PKEY_free }; + if (keyStore == nullptr) { + throw std::runtime_error("Couldn't initialize keyStore. EVP_PKEY_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Sign rsa key */ + if (!EVP_PKEY_assign_RSA(keyStore.get(), rsa)) { + throw std::runtime_error("Couldn't assign rsa. EVP_PKEY_assign_RSA(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set certificate serial number. */ + if (!ASN1_INTEGER_set(X509_get_serialNumber(x509), serialNumber)) { + throw std::runtime_error("Couldn't set serial number. ASN1_INTEGER_set(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set certificate version */ + if (!X509_set_version(x509, version)) { + throw std::runtime_error("Couldn't set version. X509_set_version(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Set certificate creation and expiration date */ + X509_gmtime_adj(X509_get_notBefore(x509), notBefore); + X509_gmtime_adj(X509_get_notAfter(x509), notAfter); + + /* Set certificate public key */ + if (!X509_set_pubkey(x509, keyStore.get())) { + throw std::runtime_error("Couldn't set public key. X509_set_pubkey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Initialize X509_NAME */ + X509_NAME* x509Name = X509_get_subject_name(x509); + if (x509Name == nullptr) { + throw std::runtime_error("Couldn't initialize X509_NAME. X509_NAME(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Add additional data to certificate */ + QMapIterator certificateInformationList(additionalData); + while (certificateInformationList.hasNext()) { + /* Read next item in list */ + certificateInformationList.next(); + + /* Set additional data */ + if (!X509_NAME_add_entry_by_txt(x509Name, certificateInformationList.key().data(), MBSTRING_UTF8, reinterpret_cast(certificateInformationList.value().data()), -1, -1, 0)) { + throw std::runtime_error("Couldn't set additional information. X509_NAME_add_entry_by_txt(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + } + + /* Set certificate info */ + if (!X509_set_issuer_name(x509, x509Name)) { + throw std::runtime_error("Couldn't set issuer name. X509_set_issuer_name(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Sign certificate */ + if (!X509_sign(x509, keyStore.get(), md)) { + throw std::runtime_error("Couldn't sign X509. X509_sign(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Write certificate file on disk. If needed */ + if (!certificateFileName.isEmpty()) { + /* Initialize BIO */ + std::unique_ptr certFile { BIO_new_file(certificateFileName.data(), "w+"), BIO_free_all }; + if (certFile == nullptr) { + throw std::runtime_error("Couldn't initialize certFile. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + + /* Write file on disk */ + if (!PEM_write_bio_X509(certFile.get(), x509)) { + throw std::runtime_error("Couldn't write certificate file on disk. PEM_write_bio_X509(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + } + } + + return x509; + } catch (std::exception& exception) { + QSimpleCrypto::QX509::error.setError(1, exception.what()); + return nullptr; + } catch (...) { + QSimpleCrypto::QX509::error.setError(2, "Unknown error!"); + return nullptr; + } +} diff --git a/client/3rd/QSimpleCrypto/sources/QX509Store.cpp b/client/3rd/QSimpleCrypto/sources/QX509Store.cpp new file mode 100644 index 000000000..bbbec1a84 --- /dev/null +++ b/client/3rd/QSimpleCrypto/sources/QX509Store.cpp @@ -0,0 +1,176 @@ +/** + * Copyright 2021 BrutalWizard (https://github.com/bru74lw1z4rd). All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution +**/ + +#include "include/QX509Store.h" + +QSimpleCrypto::QX509Store::QX509Store() +{ +} + +/// +/// \brief QSimpleCrypto::QX509::addCertificateToStore +/// \param store - OpenSSL X509_STORE. +/// \param x509 - OpenSSL X509. +/// \return Returns 'true' on success and 'false', if error happened. +/// +bool QSimpleCrypto::QX509Store::addCertificateToStore(X509_STORE* store, X509* x509) +{ + if (!X509_STORE_add_cert(store, x509)) { + QSimpleCrypto::QX509Store::error.setError(1, "Couldn't add certificate to X509_STORE. X509_STORE_add_cert(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + + return true; +} + +/// +/// \brief QSimpleCrypto::QX509Store::addLookup +/// \param store - OpenSSL X509_STORE. +/// \param method - OpenSSL X509_LOOKUP_METHOD. Example: X509_LOOKUP_file. +/// \return Returns 'true' on success and 'false', if error happened. +/// +bool QSimpleCrypto::QX509Store::addLookup(X509_STORE* store, X509_LOOKUP_METHOD* method) +{ + if (!X509_STORE_add_lookup(store, method)) { + QSimpleCrypto::QX509Store::error.setError(1, "Couldn't add lookup to X509_STORE. X509_STORE_add_lookup(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + + return true; +} + +/// +/// \brief QSimpleCrypto::QX509Store::setCertificateDepth +/// \param store - OpenSSL X509_STORE. +/// \param depth - That is the maximum number of untrusted CA certificates that can appear in a chain. Example: 0. +/// \return Returns 'true' on success and 'false', if error happened. +/// +bool QSimpleCrypto::QX509Store::setDepth(X509_STORE* store, const int& depth) +{ + if (!X509_STORE_set_depth(store, depth)) { + QSimpleCrypto::QX509Store::error.setError(1, "Couldn't set depth for X509_STORE. X509_STORE_set_depth(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + + return true; +} + +/// +/// \brief QSimpleCrypto::QX509Store::setFlag +/// \param store - OpenSSL X509_STORE. +/// \param flag - The verification flags consists of zero or more of the following flags ored together. Example: X509_V_FLAG_CRL_CHECK. +/// \return Returns 'true' on success and 'false', if error happened. +/// +bool QSimpleCrypto::QX509Store::setFlag(X509_STORE* store, const unsigned long& flag) +{ + if (!X509_STORE_set_flags(store, flag)) { + QSimpleCrypto::QX509Store::error.setError(1, "Couldn't set flag for X509_STORE. X509_STORE_set_flags(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + + return true; +} + +/// +/// \brief QSimpleCrypto::QX509Store::setFlag +/// \param store - OpenSSL X509_STORE. +/// \param purpose - Verification purpose in param to purpose. Example: X509_PURPOSE_ANY. +/// \return Returns 'true' on success and 'false', if error happened. +/// +bool QSimpleCrypto::QX509Store::setPurpose(X509_STORE* store, const int& purpose) +{ + if (!X509_STORE_set_purpose(store, purpose)) { + QSimpleCrypto::QX509Store::error.setError(1, "Couldn't set purpose for X509_STORE. X509_STORE_set_purpose(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + + return true; +} + +/// +/// \brief QSimpleCrypto::QX509Store::setTrust +/// \param store - OpenSSL X509_STORE. +/// \param trust - Trust Level. Example: X509_TRUST_SSL_SERVER. +/// \return Returns 'true' on success and 'false', if error happened. +/// +bool QSimpleCrypto::QX509Store::setTrust(X509_STORE* store, const int& trust) +{ + if (!X509_STORE_set_trust(store, trust)) { + QSimpleCrypto::QX509Store::error.setError(1, "Couldn't set trust for X509_STORE. X509_STORE_set_trust(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + + return true; +} + +/// +/// \brief QSimpleCrypto::QX509Store::setDefaultPaths +/// \param store - OpenSSL X509_STORE. +/// \return Returns 'true' on success and 'false', if error happened. +/// +bool QSimpleCrypto::QX509Store::setDefaultPaths(X509_STORE* store) +{ + if (!X509_STORE_set_default_paths(store)) { + QSimpleCrypto::QX509Store::error.setError(1, "Couldn't set default paths for X509_STORE. X509_STORE_set_default_paths(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + + return true; +} + +/// +/// \brief QSimpleCrypto::QX509Store::loadLocations +/// \param store - OpenSSL X509_STORE. +/// \param fileName - File name. Example: "caCertificate.pem". +/// \param dirPath - Path to file. Example: "path/To/File". +/// \return Returns 'true' on success and 'false', if error happened. +/// +bool QSimpleCrypto::QX509Store::loadLocations(X509_STORE* store, const QByteArray& fileName, const QByteArray& dirPath) +{ + if (!X509_STORE_load_locations(store, fileName, dirPath)) { + QSimpleCrypto::QX509Store::error.setError(1, "Couldn't load locations for X509_STORE. X509_STORE_load_locations(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + + return true; +} + +/// +/// \brief QSimpleCrypto::QX509Store::loadLocations +/// \param store - OpenSSL X509_STORE. +/// \param file - Qt QFile that will be loaded. +/// \return Returns 'true' on success and 'false', if error happened. +/// +bool QSimpleCrypto::QX509Store::loadLocations(X509_STORE* store, const QFile& file) +{ + /* Initialize QFileInfo to read information about file */ + QFileInfo info(file); + + if (!X509_STORE_load_locations(store, info.fileName().toLocal8Bit(), info.absoluteDir().path().toLocal8Bit())) { + QSimpleCrypto::QX509Store::error.setError(1, "Couldn't load locations for X509_STORE. X509_STORE_load_locations(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + + return true; +} + +/// +/// \brief QSimpleCrypto::QX509Store::loadLocations +/// \param store - OpenSSL X509_STORE. +/// \param fileInfo - Qt QFileInfo. +/// \return Returns 'true' on success and 'false', if error happened. +/// +bool QSimpleCrypto::QX509Store::loadLocations(X509_STORE* store, const QFileInfo& fileInfo) +{ + if (!X509_STORE_load_locations(store, fileInfo.fileName().toLocal8Bit(), fileInfo.absoluteDir().path().toLocal8Bit())) { + QSimpleCrypto::QX509Store::error.setError(1, "Couldn't load locations for X509_STORE. X509_STORE_load_locations(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + + return true; +} diff --git a/client/client.pro b/client/client.pro index 9d2180f75..023f0e184 100644 --- a/client/client.pro +++ b/client/client.pro @@ -16,7 +16,9 @@ include("3rd/QtSsh/src/botan/botan.pri") !android:!ios:include("3rd/SingleApplication/singleapplication.pri") include ("3rd/SortFilterProxyModel/SortFilterProxyModel.pri") include("3rd/qzxing/src/QZXing-components.pri") +include("3rd/QSimpleCrypto/QSimpleCrypto.pri") +INCLUDEPATH += $$PWD/3rd/QSimpleCrypto/include INCLUDEPATH += $$PWD/3rd/OpenSSL/include DEPENDPATH += $$PWD/3rd/OpenSSL/include @@ -37,7 +39,6 @@ HEADERS += \ core/servercontroller.h \ debug.h \ defines.h \ - encryption_helper.h \ managementserver.h \ platforms/ios/MobileUtils.h \ platforms/linux/leakdetector.h \ @@ -96,7 +97,6 @@ SOURCES += \ core/server_defs.cpp \ core/servercontroller.cpp \ debug.cpp \ - encryption_helper.cpp \ main.cpp \ managementserver.cpp \ platforms/ios/MobileUtils.cpp \ @@ -169,7 +169,6 @@ win32 { -lshlwapi \ -liphlpapi \ -lws2_32 \ - -liphlpapi \ -lgdi32 diff --git a/client/encryption_helper.cpp b/client/encryption_helper.cpp deleted file mode 100644 index 6c1bffda8..000000000 --- a/client/encryption_helper.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "encryption_helper.h" - -#include -#include -#include - -#include "openssl/evp.h" - -int gcm_encrypt(const char *plaintext, int plaintext_len, - const char *key, const char *iv, int iv_len, - char *ciphertext) -{ - return gcm_encrypt((uchar*)plaintext, plaintext_len, - (uchar*)key, (uchar*)iv, iv_len, - (uchar*)ciphertext); -} - -int gcm_decrypt(const char *ciphertext, int ciphertext_len, - const char *key, - const char *iv, int iv_len, - char *plaintext) -{ - return gcm_decrypt((uchar*)ciphertext, ciphertext_len, - (uchar*)key, (uchar*)iv, iv_len, - (uchar*)plaintext); -} - -void handleErrors() { - qDebug() << "handleErrors"; -} - -int generate_key_and_iv(unsigned char *iv, unsigned char *key) { -// unsigned char key[32]; -// unsigned char iv[16]; -// EVP_BytesToKey(EVP_aes_256_gcm(), EVP_md5(), -// NULL, -// key_file_buf, key_size, 1, // const unsigned char *data, int datal, int count, -// key, iv); - return 0; -} - -int gcm_encrypt(const unsigned char *plaintext, int plaintext_len, - const unsigned char *key, - const unsigned char *iv, int iv_len, - unsigned char *ciphertext) -{ - EVP_CIPHER_CTX *ctx; - int len; - int ciphertext_len; - - /* Create and initialise the context */ - if(!(ctx = EVP_CIPHER_CTX_new())) - handleErrors(); - - /* Initialise the encryption operation. */ - if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) - handleErrors(); - - /* - * Set IV length if default 12 bytes (96 bits) is not appropriate - */ - if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) - handleErrors(); - - /* Initialise key and IV */ - if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) - handleErrors(); - - /* - * Provide the message to be encrypted, and obtain the encrypted output. - * EVP_EncryptUpdate can be called multiple times if necessary - */ - if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) - handleErrors(); - ciphertext_len = len; - - /* - * Finalise the encryption. Normally ciphertext bytes may be written at - * this stage, but this does not occur in GCM mode - */ - if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) - handleErrors(); - ciphertext_len += len; - - /* Clean up */ - EVP_CIPHER_CTX_free(ctx); - - return ciphertext_len; -} - -int gcm_decrypt(const unsigned char *ciphertext, int ciphertext_len, - const unsigned char *key, - const unsigned char *iv, int iv_len, - unsigned char *plaintext) -{ - EVP_CIPHER_CTX *ctx; - int len; - int plaintext_len; - int ret; - - /* Create and initialise the context */ - if(!(ctx = EVP_CIPHER_CTX_new())) - handleErrors(); - - /* Initialise the decryption operation. */ - if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) - handleErrors(); - - /* Set IV length. Not necessary if this is 12 bytes (96 bits) */ - if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) - handleErrors(); - - /* Initialise key and IV */ - if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) - handleErrors(); - - /* - * Provide the message to be decrypted, and obtain the plaintext output. - * EVP_DecryptUpdate can be called multiple times if necessary - */ - if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) - handleErrors(); - plaintext_len = len; - - /* - * Finalise the decryption. A positive return value indicates success, - * anything else is a failure - the plaintext is not trustworthy. - */ - ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len); - - /* Clean up */ - EVP_CIPHER_CTX_free(ctx); - - if(ret > 0) { - /* Success */ - plaintext_len += len; - return plaintext_len; - } else { - /* Verify failed */ - return -1; - } -} - diff --git a/client/encryption_helper.h b/client/encryption_helper.h deleted file mode 100644 index ba9214087..000000000 --- a/client/encryption_helper.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef ENCRYPTION_HELPER_H -#define ENCRYPTION_HELPER_H - -#include -#include - - - -int gcm_encrypt(const char *plaintext, int plaintext_len, - const char *key, - const char *iv, int iv_len, - char *ciphertext); - -int gcm_decrypt(const char *ciphertext, int ciphertext_len, - const char *key, - const char *iv, int iv_len, - char *plaintext); - - -int gcm_encrypt(const unsigned char *plaintext, int plaintext_len, - const unsigned char *key, - const unsigned char *iv, int iv_len, - unsigned char *ciphertext); - -int gcm_decrypt(const unsigned char *ciphertext, int ciphertext_len, - const unsigned char *key, - const unsigned char *iv, int iv_len, - unsigned char *plaintext); - - -#endif // ENCRYPTION_HELPER_H diff --git a/client/secure_qsettings.cpp b/client/secure_qsettings.cpp index 0b2f138ea..46d490adc 100644 --- a/client/secure_qsettings.cpp +++ b/client/secure_qsettings.cpp @@ -1,35 +1,37 @@ #include "secure_qsettings.h" -#include "encryption_helper.h" #include "platforms/ios/MobileUtils.h" #include #include +#include "utils.h" +#include +#include "QAead.h" +#include "QBlockCipher.h" SecureQSettings::SecureQSettings(const QString &organization, const QString &application, QObject *parent) : QObject{parent}, - m_setting(organization, application, parent), + m_settings(organization, application, parent), encryptedKeys({"Servers/serversList"}) { + qDebug() << "SecureQSettings::SecureQSettings CTOR"; // load keys from system key storage #ifdef Q_OS_IOS - key = QByteArray::fromBase64(MobileUtils::readFromKeychain(settingsKeyTag).toUtf8()); - iv = QByteArray::fromBase64(MobileUtils::readFromKeychain(settingsIvTag).toUtf8()); + m_key = QByteArray::fromBase64(MobileUtils::readFromKeychain(settingsKeyTag).toUtf8()); + m_iv = QByteArray::fromBase64(MobileUtils::readFromKeychain(settingsIvTag).toUtf8()); #endif - key = "12345qwerty00000"; - iv = "000000000000000"; - bool encrypted = m_setting.value("Conf/encrypted").toBool(); + bool encrypted = m_settings.value("Conf/encrypted").toBool(); - // convert settings to encrypted + // convert settings to encrypted for if updated to >= 2.1.0 if (encryptionRequired() && ! encrypted) { - for (const QString &key : m_setting.allKeys()) { + for (const QString &key : m_settings.allKeys()) { if (encryptedKeys.contains(key)) { const QVariant &val = value(key); setValue(key, val); } } - m_setting.setValue("Conf/encrypted", true); - m_setting.sync(); + m_settings.setValue("Conf/encrypted", true); + m_settings.sync(); } } @@ -39,18 +41,36 @@ QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue return m_cache.value(key); } + if (!m_settings.contains(key)) return defaultValue; + QVariant retVal; - if (encryptionRequired() && encryptedKeys.contains(key)) { - if (!m_setting.contains(key)) return defaultValue; - QByteArray encryptedValue = m_setting.value(key).toByteArray(); - QByteArray decryptedValue = decryptText(encryptedValue); + // check if value is not encrypted, v. < 2.0.x + retVal = m_settings.value(key); + if (retVal.isValid()) { + if (retVal.userType() == QVariant::ByteArray && + retVal.toByteArray().mid(0, magicString.size()) == magicString) { + + if (m_key.isEmpty() || m_iv.isEmpty()) { + qCritical() << "SecureQSettings::setValue Decryption requested, but key is empty"; + return {}; + } + + QByteArray encryptedValue = retVal.toByteArray().mid(magicString.size()); + + QByteArray decryptedValue = decryptText(encryptedValue); + QDataStream ds(&decryptedValue, QIODevice::ReadOnly); - QDataStream ds(&decryptedValue, QIODevice::ReadOnly); - ds >> retVal; + ds >> retVal; + + if (!retVal.isValid()) { + qWarning() << "SecureQSettings::value settings decryption failed"; + } + } } else { - retVal = m_setting.value(key, defaultValue); + qWarning() << "SecureQSettings::value invalid QVariant value"; + retVal = QVariant(); } m_cache.insert(key, retVal); @@ -61,17 +81,24 @@ QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue void SecureQSettings::setValue(const QString &key, const QVariant &value) { if (encryptionRequired() && encryptedKeys.contains(key)) { - QByteArray decryptedValue; - { - QDataStream ds(&decryptedValue, QIODevice::WriteOnly); - ds << value; + if (!m_key.isEmpty() && !m_iv.isEmpty()) { + QByteArray decryptedValue; + { + QDataStream ds(&decryptedValue, QIODevice::WriteOnly); + ds << value; + } + + QByteArray encryptedValue = encryptText(decryptedValue); + m_settings.setValue(key, magicString + encryptedValue); + } + else { + qCritical() << "SecureQSettings::setValue Encryption required, but key is empty"; + return; } - QByteArray encryptedValue = encryptText(decryptedValue); - m_setting.setValue(key, encryptedValue); } else { - m_setting.setValue(key, value); + m_settings.setValue(key, value); } m_cache.insert(key, value); @@ -80,7 +107,7 @@ void SecureQSettings::setValue(const QString &key, const QVariant &value) void SecureQSettings::remove(const QString &key) { - m_setting.remove(key); + m_settings.remove(key); m_cache.remove(key); sync(); @@ -88,13 +115,13 @@ void SecureQSettings::remove(const QString &key) void SecureQSettings::sync() { - m_setting.sync(); + m_settings.sync(); } QByteArray SecureQSettings::backupAppConfig() const { QMap cfg; - for (const QString &key : m_setting.allKeys()) { + for (const QString &key : m_settings.allKeys()) { cfg.insert(key, value(key)); } @@ -125,20 +152,16 @@ void SecureQSettings::restoreAppConfig(const QByteArray &base64Cfg) } -QByteArray SecureQSettings::encryptText(const QByteArray& value) const { - char cipherText[UINT16_MAX]; - int cipherTextSize = gcm_encrypt(value.constData(), value.size(), - key.constData(), iv.constData(), iv_len, cipherText); - - return QByteArray::fromRawData((const char *)cipherText, cipherTextSize); +QByteArray SecureQSettings::encryptText(const QByteArray& value) const +{ + QSimpleCrypto::QBlockCipher cipher; + return cipher.encryptAesBlockCipher(value, m_key, m_iv); } -QByteArray SecureQSettings::decryptText(const QByteArray& ba) const { - char decryptPlainText[UINT16_MAX]; - gcm_decrypt(ba.data(), ba.size(), - key.constData(), iv.constData(), iv_len, decryptPlainText); - - return QByteArray::fromRawData(decryptPlainText, ba.size()); +QByteArray SecureQSettings::decryptText(const QByteArray& ba) const +{ + QSimpleCrypto::QBlockCipher cipher; + return cipher.decryptAesBlockCipher(ba, m_key, m_iv); } bool SecureQSettings::encryptionRequired() const diff --git a/client/secure_qsettings.h b/client/secure_qsettings.h index 3fcd4ed7c..ae2a19b72 100644 --- a/client/secure_qsettings.h +++ b/client/secure_qsettings.h @@ -7,6 +7,7 @@ constexpr const char* settingsKeyTag = "settingsKeyTag"; constexpr const char* settingsIvTag = "settingsIvTag"; + class SecureQSettings : public QObject { public: @@ -26,15 +27,17 @@ class SecureQSettings : public QObject bool encryptionRequired() const; private: - QSettings m_setting; + QSettings m_settings; mutable QMap m_cache; QStringList encryptedKeys; // encode only key listed here - QByteArray key; - QByteArray iv; - int iv_len {16}; + QByteArray m_key; + QByteArray m_iv; + + const QByteArray magicString { "EncData" }; // Magic keyword used for mark encrypted QByteArray + }; #endif // SECUREQSETTINGS_H diff --git a/client/settings.cpp b/client/settings.cpp index c8069f70f..21deb0bd1 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -8,7 +8,6 @@ const char Settings::cloudFlareNs1[] = "1.1.1.1"; const char Settings::cloudFlareNs2[] = "1.0.0.1"; -//SecureFormat Settings::m_secureFormat; Settings::Settings(QObject* parent) : QObject(parent), diff --git a/client/settings.h b/client/settings.h index 39c9919c0..18337f0d7 100644 --- a/client/settings.h +++ b/client/settings.h @@ -11,7 +11,6 @@ #include "core/defs.h" #include "containers/containers_defs.h" -#include "encryption_helper.h" #include "secure_qsettings.h" using namespace amnezia; From 14384131f41960b0fc9343470f2b5ee4166dc0b3 Mon Sep 17 00:00:00 2001 From: pokamest Date: Wed, 24 Aug 2022 07:38:13 -0700 Subject: [PATCH 15/20] Secure config WIP --- .../3rd/QSimpleCrypto/include/QBlockCipher.h | 1 + .../QSimpleCrypto/sources/QBlockCipher.cpp | 9 +++ client/platforms/ios/MobileUtils.cpp | 4 +- client/platforms/ios/MobileUtils.h | 5 +- client/platforms/ios/MobileUtils.mm | 17 ++--- client/secure_qsettings.cpp | 69 ++++++++++++++++--- client/secure_qsettings.h | 6 +- 7 files changed, 83 insertions(+), 28 deletions(-) diff --git a/client/3rd/QSimpleCrypto/include/QBlockCipher.h b/client/3rd/QSimpleCrypto/include/QBlockCipher.h index af57b650f..e7b83a885 100644 --- a/client/3rd/QSimpleCrypto/include/QBlockCipher.h +++ b/client/3rd/QSimpleCrypto/include/QBlockCipher.h @@ -40,6 +40,7 @@ namespace QSimpleCrypto /// \return Returns random bytes. /// QByteArray generateRandomBytes(const int& size); + QByteArray generateSecureRandomBytes(const int& size); /// /// \brief encryptAesBlockCipher - Function encrypts data with Aes Block Cipher algorithm. diff --git a/client/3rd/QSimpleCrypto/sources/QBlockCipher.cpp b/client/3rd/QSimpleCrypto/sources/QBlockCipher.cpp index c01b9a2f8..8b86ab98c 100644 --- a/client/3rd/QSimpleCrypto/sources/QBlockCipher.cpp +++ b/client/3rd/QSimpleCrypto/sources/QBlockCipher.cpp @@ -26,6 +26,15 @@ QByteArray QSimpleCrypto::QBlockCipher::generateRandomBytes(const int& size) return buffer; } +QByteArray QSimpleCrypto::QBlockCipher::generateSecureRandomBytes(const int &size) +{ + unsigned char arr[sizeof(size)]; + RAND_priv_bytes(arr, sizeof(size)); + + QByteArray buffer = QByteArray(reinterpret_cast(arr), size); + return buffer; +} + /// /// \brief QSimpleCrypto::QBlockCipher::encryptAesBlockCipher - Function encrypts data with Aes Block Cipher algorithm. /// \param data - Data that will be encrypted. diff --git a/client/platforms/ios/MobileUtils.cpp b/client/platforms/ios/MobileUtils.cpp index 771e78559..3e82bb8c8 100644 --- a/client/platforms/ios/MobileUtils.cpp +++ b/client/platforms/ios/MobileUtils.cpp @@ -2,5 +2,5 @@ void MobileUtils::shareText(const QStringList&) {} -void MobileUtils::writeToKeychain(const QString&, const QString&) {} -QString MobileUtils::readFromKeychain(const QString&) { return {}; } +void MobileUtils::writeToKeychain(const QString&, const QByteArray &) {} +QByteArray MobileUtils::readFromKeychain(const QString&) { return {}; } diff --git a/client/platforms/ios/MobileUtils.h b/client/platforms/ios/MobileUtils.h index 49fcdce0d..045ababb6 100644 --- a/client/platforms/ios/MobileUtils.h +++ b/client/platforms/ios/MobileUtils.h @@ -13,8 +13,9 @@ class MobileUtils : public QObject { public slots: static void shareText(const QStringList& filesToSend); - static void writeToKeychain(const QString& tag, const QString& value); - static QString readFromKeychain(const QString& tag); + static void writeToKeychain(const QString& tag, const QByteArray& value); + static bool deleteFromKeychain(const QString& tag); + static QByteArray readFromKeychain(const QString& tag); }; #endif // MOBILEUTILS_H diff --git a/client/platforms/ios/MobileUtils.mm b/client/platforms/ios/MobileUtils.mm index 4a2e43e6b..bfe82a6a0 100644 --- a/client/platforms/ios/MobileUtils.mm +++ b/client/platforms/ios/MobileUtils.mm @@ -35,7 +35,7 @@ } } -bool deleteFromKeychain(const QString& tag) { +bool MobileUtils::deleteFromKeychain(const QString& tag) { NSData* nsTag = [tag.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; NSDictionary *deleteQuery = @{ (id)kSecAttrAccount: nsTag, @@ -46,17 +46,14 @@ bool deleteFromKeychain(const QString& tag) { if (status != errSecSuccess) { qDebug() << "Error deleteFromKeychain" << status; return false; - } else { - qDebug() << "OK deleteFromKeychain"; - return true; } } -void MobileUtils::writeToKeychain(const QString& tag, const QString& value) { +void MobileUtils::writeToKeychain(const QString& tag, const QByteArray& value) { deleteFromKeychain(tag); NSData* nsTag = [tag.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; - NSData* nsValue = [value.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; + NSData* nsValue = value.toNSData(); NSDictionary* addQuery = @{ (id)kSecAttrAccount: nsTag, (id)kSecClass: (id)kSecClassGenericPassword, @@ -66,12 +63,10 @@ bool deleteFromKeychain(const QString& tag) { OSStatus status = SecItemAdd((__bridge CFDictionaryRef)addQuery, NULL); if (status != errSecSuccess) { qDebug() << "Error writeToKeychain" << status; - } else { - qDebug() << "OK writeToKeychain"; } } -QString MobileUtils::readFromKeychain(const QString& tag) { +QByteArray MobileUtils::readFromKeychain(const QString& tag) { NSData* nsTag = [tag.toNSString() dataUsingEncoding:NSUTF8StringEncoding]; NSData* nsValue = NULL; @@ -85,11 +80,9 @@ bool deleteFromKeychain(const QString& tag) { (CFTypeRef *)&nsValue); if (status != errSecSuccess) { qDebug() << "Error readFromKeychain" << status; - } else { - qDebug() << "OK readFromKeychain" << nsValue; } - QString result; + QByteArray result; if (nsValue) { result = QByteArray::fromNSData(nsValue); CFRelease(nsValue); diff --git a/client/secure_qsettings.cpp b/client/secure_qsettings.cpp index 46d490adc..d77224307 100644 --- a/client/secure_qsettings.cpp +++ b/client/secure_qsettings.cpp @@ -14,11 +14,6 @@ SecureQSettings::SecureQSettings(const QString &organization, const QString &app encryptedKeys({"Servers/serversList"}) { qDebug() << "SecureQSettings::SecureQSettings CTOR"; - // load keys from system key storage -#ifdef Q_OS_IOS - m_key = QByteArray::fromBase64(MobileUtils::readFromKeychain(settingsKeyTag).toUtf8()); - m_iv = QByteArray::fromBase64(MobileUtils::readFromKeychain(settingsIvTag).toUtf8()); -#endif bool encrypted = m_settings.value("Conf/encrypted").toBool(); @@ -51,7 +46,7 @@ QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue if (retVal.userType() == QVariant::ByteArray && retVal.toByteArray().mid(0, magicString.size()) == magicString) { - if (m_key.isEmpty() || m_iv.isEmpty()) { + if (getEncKey().isEmpty() || getEncIv().isEmpty()) { qCritical() << "SecureQSettings::setValue Decryption requested, but key is empty"; return {}; } @@ -65,6 +60,7 @@ QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue if (!retVal.isValid()) { qWarning() << "SecureQSettings::value settings decryption failed"; + retVal = QVariant(); } } } @@ -81,7 +77,7 @@ QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue void SecureQSettings::setValue(const QString &key, const QVariant &value) { if (encryptionRequired() && encryptedKeys.contains(key)) { - if (!m_key.isEmpty() && !m_iv.isEmpty()) { + if (!getEncKey().isEmpty() && !getEncIv().isEmpty()) { QByteArray decryptedValue; { QDataStream ds(&decryptedValue, QIODevice::WriteOnly); @@ -155,22 +151,75 @@ void SecureQSettings::restoreAppConfig(const QByteArray &base64Cfg) QByteArray SecureQSettings::encryptText(const QByteArray& value) const { QSimpleCrypto::QBlockCipher cipher; - return cipher.encryptAesBlockCipher(value, m_key, m_iv); + return cipher.encryptAesBlockCipher(value, getEncKey(), getEncIv()); } QByteArray SecureQSettings::decryptText(const QByteArray& ba) const { QSimpleCrypto::QBlockCipher cipher; - return cipher.decryptAesBlockCipher(ba, m_key, m_iv); + return cipher.decryptAesBlockCipher(ba, getEncKey(), getEncIv()); } bool SecureQSettings::encryptionRequired() const { -#if defined Q_OS_ANDROID || defined Q_OS_IOS +#if defined Q_OS_IOS // || defined Q_OS_ANDROID return true; #endif return false; } +QByteArray SecureQSettings::getEncKey() const +{ + // load keys from system key storage + m_key = MobileUtils::readFromKeychain(settingsKeyTag); + + if (m_key.isEmpty()) { + // Create new key + QSimpleCrypto::QBlockCipher cipher; + QByteArray key = cipher.generateSecureRandomBytes(32); + if (key.isEmpty()) { + qCritical() << "SecureQSettings::getEncKey Unable to generate new enc key"; + } + + MobileUtils::writeToKeychain(settingsKeyTag, key); + + // check + m_key = MobileUtils::readFromKeychain(settingsKeyTag); + if (key != m_key) { + qCritical() << "SecureQSettings::getEncKey Unable to store key in keychain" << key.size() << m_key.size(); + return {}; + } + } + //qDebug() << "SecureQSettings::getEncKey() key" << m_key.size(); + + return m_key; +} + +QByteArray SecureQSettings::getEncIv() const +{ + // load keys from system key storage + m_iv = MobileUtils::readFromKeychain(settingsIvTag); + + if (m_iv.isEmpty()) { + // Create new IV + QSimpleCrypto::QBlockCipher cipher; + QByteArray iv = cipher.generateSecureRandomBytes(32); + if (iv.isEmpty()) { + qCritical() << "SecureQSettings::getEncIv Unable to generate new enc IV"; + } + MobileUtils::writeToKeychain(settingsIvTag, iv); + + // check + m_iv = MobileUtils::readFromKeychain(settingsIvTag); + if (iv != m_iv) { + qCritical() << "SecureQSettings::getEncIv Unable to store IV in keychain" << iv.size() << m_iv.size(); + return {}; + } + } + //qDebug() << "SecureQSettings::getEncIv() iv" << m_iv.size(); + + return m_iv; +} + diff --git a/client/secure_qsettings.h b/client/secure_qsettings.h index ae2a19b72..b36de1eb1 100644 --- a/client/secure_qsettings.h +++ b/client/secure_qsettings.h @@ -26,6 +26,8 @@ class SecureQSettings : public QObject bool encryptionRequired() const; + QByteArray getEncKey() const; + QByteArray getEncIv() const; private: QSettings m_settings; @@ -33,8 +35,8 @@ class SecureQSettings : public QObject QStringList encryptedKeys; // encode only key listed here - QByteArray m_key; - QByteArray m_iv; + mutable QByteArray m_key; + mutable QByteArray m_iv; const QByteArray magicString { "EncData" }; // Magic keyword used for mark encrypted QByteArray From 415d18338eab1c62d070b2cc0dae807ce068eee0 Mon Sep 17 00:00:00 2001 From: pokamest Date: Wed, 24 Aug 2022 18:51:35 +0300 Subject: [PATCH 16/20] Secure config WIP --- client/platforms/ios/MobileUtils.cpp | 1 + client/secure_qsettings.cpp | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/client/platforms/ios/MobileUtils.cpp b/client/platforms/ios/MobileUtils.cpp index 3e82bb8c8..4667cc25a 100644 --- a/client/platforms/ios/MobileUtils.cpp +++ b/client/platforms/ios/MobileUtils.cpp @@ -3,4 +3,5 @@ void MobileUtils::shareText(const QStringList&) {} void MobileUtils::writeToKeychain(const QString&, const QByteArray &) {} +bool MobileUtils::deleteFromKeychain(const QString& tag) { return false; } QByteArray MobileUtils::readFromKeychain(const QString&) { return {}; } diff --git a/client/secure_qsettings.cpp b/client/secure_qsettings.cpp index d77224307..488feb490 100644 --- a/client/secure_qsettings.cpp +++ b/client/secure_qsettings.cpp @@ -191,7 +191,6 @@ QByteArray SecureQSettings::getEncKey() const return {}; } } - //qDebug() << "SecureQSettings::getEncKey() key" << m_key.size(); return m_key; } @@ -217,7 +216,6 @@ QByteArray SecureQSettings::getEncIv() const return {}; } } - //qDebug() << "SecureQSettings::getEncIv() iv" << m_iv.size(); return m_iv; } From 510a564797d6f3b268dea20b8b14323f6d71466c Mon Sep 17 00:00:00 2001 From: pokamest Date: Thu, 25 Aug 2022 12:47:02 +0300 Subject: [PATCH 17/20] App refactoring --- client/amnezia_application.cpp | 212 +++++++++++++++++ client/amnezia_application.h | 52 +++++ client/client.pro | 108 ++++----- client/main.cpp | 214 ++---------------- client/settings.h | 2 + client/ui/models/containers_model.cpp | 7 +- client/ui/models/containers_model.h | 4 +- client/ui/models/protocols_model.cpp | 3 +- client/ui/models/protocols_model.h | 4 +- client/ui/models/sites_model.cpp | 5 +- client/ui/models/sites_model.h | 4 +- client/ui/pages_logic/AppSettingsLogic.cpp | 16 +- .../ui/pages_logic/GeneralSettingsLogic.cpp | 14 +- .../ui/pages_logic/NetworkSettingsLogic.cpp | 16 +- client/ui/pages_logic/PageLogicBase.cpp | 4 +- client/ui/pages_logic/PageLogicBase.h | 2 +- .../ui/pages_logic/ServerContainersLogic.cpp | 28 +-- client/ui/pages_logic/ServerListLogic.cpp | 6 +- client/ui/pages_logic/ServerSettingsLogic.cpp | 46 ++-- .../ui/pages_logic/ShareConnectionLogic.cpp | 34 +-- client/ui/pages_logic/SitesLogic.cpp | 24 +- client/ui/pages_logic/StartPageLogic.cpp | 8 +- client/ui/pages_logic/VpnLogic.cpp | 28 +-- client/ui/pages_logic/WizardLogic.cpp | 4 +- .../ui/pages_logic/protocols/CloakLogic.cpp | 10 +- client/ui/pages_logic/protocols/CloakLogic.h | 1 - .../ui/pages_logic/protocols/OpenVpnLogic.cpp | 10 +- .../ui/pages_logic/protocols/OpenVpnLogic.h | 1 - .../protocols/OtherProtocolsLogic.cpp | 2 +- .../protocols/OtherProtocolsLogic.h | 1 - .../protocols/ShadowSocksLogic.cpp | 10 +- .../pages_logic/protocols/ShadowSocksLogic.h | 1 - client/ui/uilogic.cpp | 45 ++-- client/ui/uilogic.h | 6 +- client/vpnconnection.cpp | 35 ++- client/vpnconnection.h | 4 +- 36 files changed, 527 insertions(+), 444 deletions(-) create mode 100644 client/amnezia_application.cpp create mode 100644 client/amnezia_application.h diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp new file mode 100644 index 000000000..85762a078 --- /dev/null +++ b/client/amnezia_application.cpp @@ -0,0 +1,212 @@ +#include "amnezia_application.h" + +#include +#include +#include + + +#include "QZXing.h" + +#include "debug.h" +#include "defines.h" + + +#include "platforms/ios/QRCodeReaderBase.h" +//#include "platforms/ios/MobileUtils.h" + +#include "ui/pages.h" + +#include "ui/pages_logic/AppSettingsLogic.h" +#include "ui/pages_logic/GeneralSettingsLogic.h" +#include "ui/pages_logic/NetworkSettingsLogic.h" +#include "ui/pages_logic/NewServerProtocolsLogic.h" +#include "ui/pages_logic/QrDecoderLogic.h" +#include "ui/pages_logic/ServerConfiguringProgressLogic.h" +#include "ui/pages_logic/ServerContainersLogic.h" +#include "ui/pages_logic/ServerListLogic.h" +#include "ui/pages_logic/ServerSettingsLogic.h" +#include "ui/pages_logic/ServerContainersLogic.h" +#include "ui/pages_logic/ShareConnectionLogic.h" +#include "ui/pages_logic/SitesLogic.h" +#include "ui/pages_logic/StartPageLogic.h" +#include "ui/pages_logic/VpnLogic.h" +#include "ui/pages_logic/WizardLogic.h" + +#include "ui/pages_logic/protocols/CloakLogic.h" +#include "ui/pages_logic/protocols/OpenVpnLogic.h" +#include "ui/pages_logic/protocols/ShadowSocksLogic.h" + + +AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecondary, + SingleApplication::Options options, int timeout, const QString &userData): + #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + QAPPLICATION_CLASS(argc, argv); + #else + SingleApplication(argc, argv, allowSecondary, options, timeout, userData) + #endif + + +{ + setQuitOnLastWindowClosed(false); + m_settings = std::shared_ptr(new Settings); + +// QObject::connect(&app, &QCoreApplication::aboutToQuit, uiLogic, [&engine, uiLogic](){ +// QObject::disconnect(engine, 0,0,0); +// delete engine; + +// QObject::disconnect(uiLogic, 0,0,0); +// delete uiLogic; + // }); +} + +AmneziaApplication::~AmneziaApplication() +{ + QObject::disconnect(m_engine, 0,0,0); + delete m_engine; + + QObject::disconnect(m_uiLogic, 0,0,0); + delete m_uiLogic; +} + +void AmneziaApplication::init() +{ + m_engine = new QQmlApplicationEngine; + m_uiLogic = new UiLogic(m_settings); + + const QUrl url(QStringLiteral("qrc:/ui/qml/main.qml")); + QObject::connect(m_engine, &QQmlApplicationEngine::objectCreated, + this, [url](QObject *obj, const QUrl &objUrl) { + if (!obj && url == objUrl) + QCoreApplication::exit(-1); + }, Qt::QueuedConnection); + + m_engine->rootContext()->setContextProperty("Debug", &Debug::Instance()); + + m_engine->rootContext()->setContextProperty("UiLogic", m_uiLogic); + + m_engine->rootContext()->setContextProperty("AppSettingsLogic", m_uiLogic->appSettingsLogic()); + m_engine->rootContext()->setContextProperty("GeneralSettingsLogic", m_uiLogic->generalSettingsLogic()); + m_engine->rootContext()->setContextProperty("NetworkSettingsLogic", m_uiLogic->networkSettingsLogic()); + m_engine->rootContext()->setContextProperty("NewServerProtocolsLogic", m_uiLogic->newServerProtocolsLogic()); + m_engine->rootContext()->setContextProperty("QrDecoderLogic", m_uiLogic->qrDecoderLogic()); + m_engine->rootContext()->setContextProperty("ServerConfiguringProgressLogic", m_uiLogic->serverConfiguringProgressLogic()); + m_engine->rootContext()->setContextProperty("ServerListLogic", m_uiLogic->serverListLogic()); + m_engine->rootContext()->setContextProperty("ServerSettingsLogic", m_uiLogic->serverSettingsLogic()); + m_engine->rootContext()->setContextProperty("ServerContainersLogic", m_uiLogic->serverprotocolsLogic()); + m_engine->rootContext()->setContextProperty("ShareConnectionLogic", m_uiLogic->shareConnectionLogic()); + m_engine->rootContext()->setContextProperty("SitesLogic", m_uiLogic->sitesLogic()); + m_engine->rootContext()->setContextProperty("StartPageLogic", m_uiLogic->startPageLogic()); + m_engine->rootContext()->setContextProperty("VpnLogic", m_uiLogic->vpnLogic()); + m_engine->rootContext()->setContextProperty("WizardLogic", m_uiLogic->wizardLogic()); + +#if defined(Q_OS_IOS) + setStartPageLogic(uiLogic->startPageLogic()); +#endif + + m_engine->load(url); + + if (m_engine->rootObjects().size() > 0) { + m_uiLogic->setQmlRoot(m_engine->rootObjects().at(0)); + } + + if (m_settings->isSaveLogs()) { + if (!Debug::init()) { + qWarning() << "Initialization of debug subsystem failed"; + } + } + +#ifdef Q_OS_WIN + if (m_parser.isSet("a")) m_uiLogic->showOnStartup(); + else emit m_uiLogic->show(); +#else + uiLogic->showOnStartup(); +#endif + + // TODO - fix +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) + if (isPrimary()) { + QObject::connect(this, &SingleApplication::instanceStarted, m_uiLogic, [this](){ + qDebug() << "Secondary instance started, showing this window instead"; + emit m_uiLogic->show(); + emit m_uiLogic->raise(); + }); + } +#endif +} + +void AmneziaApplication::registerTypes() +{ + QZXing::registerQMLTypes(); + + qRegisterMetaType("VpnProtocol::VpnConnectionState"); + qRegisterMetaType("ServerCredentials"); + + qRegisterMetaType("DockerContainer"); + qRegisterMetaType("TransportProto"); + qRegisterMetaType("Proto"); + qRegisterMetaType("ServiceType"); + qRegisterMetaType("Page"); + qRegisterMetaType("ConnectionState"); + + qRegisterMetaType("PageProtocolLogicBase *"); + + + + declareQmlPageEnum(); + declareQmlProtocolEnum(); + declareQmlContainerEnum(); + + qmlRegisterType("PageType", 1, 0, "PageType"); + qmlRegisterType("QRCodeReader", 1, 0, "QRCodeReader"); + + QScopedPointer containerProps(new ContainerProps); + qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", containerProps.get()); + + QScopedPointer protocolProps(new ProtocolProps); + qmlRegisterSingletonInstance("ProtocolProps", 1, 0, "ProtocolProps", protocolProps.get()); +} + +void AmneziaApplication::loadFonts() +{ + QFontDatabase::addApplicationFont(":/fonts/Lato-Black.ttf"); + QFontDatabase::addApplicationFont(":/fonts/Lato-BlackItalic.ttf"); + QFontDatabase::addApplicationFont(":/fonts/Lato-Bold.ttf"); + QFontDatabase::addApplicationFont(":/fonts/Lato-BoldItalic.ttf"); + QFontDatabase::addApplicationFont(":/fonts/Lato-Italic.ttf"); + QFontDatabase::addApplicationFont(":/fonts/Lato-Light.ttf"); + QFontDatabase::addApplicationFont(":/fonts/Lato-LightItalic.ttf"); + QFontDatabase::addApplicationFont(":/fonts/Lato-Regular.ttf"); + QFontDatabase::addApplicationFont(":/fonts/Lato-Thin.ttf"); + QFontDatabase::addApplicationFont(":/fonts/Lato-ThinItalic.ttf"); +} + +void AmneziaApplication::loadTranslator() +{ + m_translator = new QTranslator; + if (m_translator->load(QLocale(), QString("amneziavpn"), QLatin1String("_"), QLatin1String(":/translations"))) { + installTranslator(m_translator); + } +} + +void AmneziaApplication::parseCommands() +{ + m_parser.setApplicationDescription(APPLICATION_NAME); + m_parser.addHelpOption(); + m_parser.addVersionOption(); + + QCommandLineOption c_autostart {{"a", "autostart"}, "System autostart"}; + m_parser.addOption(c_autostart); + + QCommandLineOption c_cleanup {{"c", "cleanup"}, "Cleanup logs"}; + m_parser.addOption(c_cleanup); + + m_parser.process(*this); + + if (m_parser.isSet(c_cleanup)) { + Debug::cleanUp(); + QTimer::singleShot(100,[this]{ + quit(); + }); + exec(); + } +} diff --git a/client/amnezia_application.h b/client/amnezia_application.h new file mode 100644 index 000000000..d7a768338 --- /dev/null +++ b/client/amnezia_application.h @@ -0,0 +1,52 @@ +#ifndef AMNEZIA_APPLICATION_H +#define AMNEZIA_APPLICATION_H + +#include +#include + +#include +#include +#include + +#include "settings.h" + +#include "ui/uilogic.h" + +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) + #define AMNEZIA_BASE_CLASS SingleApplication + #define QAPPLICATION_CLASS QGuiApplication + #include "singleapplication.h" + //#undef QAPPLICATION_CLASS +#else + #define AMNEZIA_BASE_CLASS QApplication +#endif + +class AmneziaApplication : public AMNEZIA_BASE_CLASS +{ + Q_OBJECT +public: +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + AmneziaApplication(int &argc, char *argv[]); +#else + AmneziaApplication(int &argc, char *argv[], bool allowSecondary = false, + SingleApplication::Options options = SingleApplication::User, int timeout = 1000, const QString &userData = {} ); +#endif + virtual ~AmneziaApplication(); + + void init(); + void registerTypes(); + void loadFonts(); + void loadTranslator(); + void parseCommands(); + +private: + QQmlApplicationEngine *m_engine; + UiLogic *m_uiLogic; + std::shared_ptr m_settings; + + QTranslator* m_translator; + QCommandLineParser m_parser; + +}; + +#endif // AMNEZIA_APPLICATION_H diff --git a/client/client.pro b/client/client.pro index 023f0e184..5d9ab1ea7 100644 --- a/client/client.pro +++ b/client/client.pro @@ -24,25 +24,26 @@ DEPENDPATH += $$PWD/3rd/OpenSSL/include HEADERS += \ ../ipc/ipc.h \ - configurators/cloak_configurator.h \ - configurators/ikev2_configurator.h \ - configurators/shadowsocks_configurator.h \ - configurators/ssh_configurator.h \ - configurators/vpn_configurator.h \ - configurators/wireguard_configurator.h \ + amnezia_application.h \ + configurators/cloak_configurator.h \ + configurators/ikev2_configurator.h \ + configurators/shadowsocks_configurator.h \ + configurators/ssh_configurator.h \ + configurators/vpn_configurator.h \ + configurators/wireguard_configurator.h \ containers/containers_defs.h \ core/defs.h \ core/errorstrings.h \ configurators/openvpn_configurator.h \ - core/scripts_registry.h \ - core/server_defs.h \ + core/scripts_registry.h \ + core/server_defs.h \ core/servercontroller.h \ debug.h \ defines.h \ managementserver.h \ platforms/ios/MobileUtils.h \ platforms/linux/leakdetector.h \ - protocols/protocols_defs.h \ + protocols/protocols_defs.h \ secure_qsettings.h \ settings.h \ ui/notificationhandler.h \ @@ -52,10 +53,10 @@ HEADERS += \ ui/pages_logic/AppSettingsLogic.h \ ui/pages_logic/GeneralSettingsLogic.h \ ui/pages_logic/NetworkSettingsLogic.h \ - ui/pages_logic/NewServerProtocolsLogic.h \ + ui/pages_logic/NewServerProtocolsLogic.h \ ui/pages_logic/PageLogicBase.h \ - ui/pages_logic/QrDecoderLogic.h \ - ui/pages_logic/ServerConfiguringProgressLogic.h \ + ui/pages_logic/QrDecoderLogic.h \ + ui/pages_logic/ServerConfiguringProgressLogic.h \ ui/pages_logic/ServerContainersLogic.h \ ui/pages_logic/ServerListLogic.h \ ui/pages_logic/ServerSettingsLogic.h \ @@ -64,16 +65,16 @@ HEADERS += \ ui/pages_logic/StartPageLogic.h \ ui/pages_logic/VpnLogic.h \ ui/pages_logic/WizardLogic.h \ - ui/pages_logic/protocols/CloakLogic.h \ - ui/pages_logic/protocols/OpenVpnLogic.h \ - ui/pages_logic/protocols/OtherProtocolsLogic.h \ - ui/pages_logic/protocols/PageProtocolLogicBase.h \ - ui/pages_logic/protocols/ShadowSocksLogic.h \ + ui/pages_logic/protocols/CloakLogic.h \ + ui/pages_logic/protocols/OpenVpnLogic.h \ + ui/pages_logic/protocols/OtherProtocolsLogic.h \ + ui/pages_logic/protocols/PageProtocolLogicBase.h \ + ui/pages_logic/protocols/ShadowSocksLogic.h \ ui/property_helper.h \ ui/models/servers_model.h \ ui/uilogic.h \ - ui/qautostart.h \ - ui/models/sites_model.h \ + ui/qautostart.h \ + ui/models/sites_model.h \ utils.h \ vpnconnection.h \ protocols/vpnprotocol.h \ @@ -84,24 +85,25 @@ HEADERS += \ platforms/ios/QRCodeReaderBase.h SOURCES += \ - configurators/cloak_configurator.cpp \ - configurators/ikev2_configurator.cpp \ - configurators/shadowsocks_configurator.cpp \ - configurators/ssh_configurator.cpp \ - configurators/vpn_configurator.cpp \ - configurators/wireguard_configurator.cpp \ + amnezia_application.cpp \ + configurators/cloak_configurator.cpp \ + configurators/ikev2_configurator.cpp \ + configurators/shadowsocks_configurator.cpp \ + configurators/ssh_configurator.cpp \ + configurators/vpn_configurator.cpp \ + configurators/wireguard_configurator.cpp \ containers/containers_defs.cpp \ - core/errorstrings.cpp \ + core/errorstrings.cpp \ configurators/openvpn_configurator.cpp \ - core/scripts_registry.cpp \ - core/server_defs.cpp \ + core/scripts_registry.cpp \ + core/server_defs.cpp \ core/servercontroller.cpp \ debug.cpp \ main.cpp \ managementserver.cpp \ platforms/ios/MobileUtils.cpp \ platforms/linux/leakdetector.cpp \ - protocols/protocols_defs.cpp \ + protocols/protocols_defs.cpp \ secure_qsettings.cpp \ settings.cpp \ ui/notificationhandler.cpp \ @@ -110,10 +112,10 @@ SOURCES += \ ui/pages_logic/AppSettingsLogic.cpp \ ui/pages_logic/GeneralSettingsLogic.cpp \ ui/pages_logic/NetworkSettingsLogic.cpp \ - ui/pages_logic/NewServerProtocolsLogic.cpp \ + ui/pages_logic/NewServerProtocolsLogic.cpp \ ui/pages_logic/PageLogicBase.cpp \ - ui/pages_logic/QrDecoderLogic.cpp \ - ui/pages_logic/ServerConfiguringProgressLogic.cpp \ + ui/pages_logic/QrDecoderLogic.cpp \ + ui/pages_logic/ServerConfiguringProgressLogic.cpp \ ui/pages_logic/ServerContainersLogic.cpp \ ui/pages_logic/ServerListLogic.cpp \ ui/pages_logic/ServerSettingsLogic.cpp \ @@ -122,15 +124,15 @@ SOURCES += \ ui/pages_logic/StartPageLogic.cpp \ ui/pages_logic/VpnLogic.cpp \ ui/pages_logic/WizardLogic.cpp \ - ui/pages_logic/protocols/CloakLogic.cpp \ - ui/pages_logic/protocols/OpenVpnLogic.cpp \ - ui/pages_logic/protocols/OtherProtocolsLogic.cpp \ - ui/pages_logic/protocols/PageProtocolLogicBase.cpp \ - ui/pages_logic/protocols/ShadowSocksLogic.cpp \ + ui/pages_logic/protocols/CloakLogic.cpp \ + ui/pages_logic/protocols/OpenVpnLogic.cpp \ + ui/pages_logic/protocols/OtherProtocolsLogic.cpp \ + ui/pages_logic/protocols/PageProtocolLogicBase.cpp \ + ui/pages_logic/protocols/ShadowSocksLogic.cpp \ ui/models/servers_model.cpp \ ui/uilogic.cpp \ - ui/qautostart.cpp \ - ui/models/sites_model.cpp \ + ui/qautostart.cpp \ + ui/models/sites_model.cpp \ utils.cpp \ vpnconnection.cpp \ protocols/vpnprotocol.cpp \ @@ -249,20 +251,20 @@ android { DISTFILES += \ - android/AndroidManifest.xml \ - android/build.gradle \ - android/gradle/wrapper/gradle-wrapper.jar \ - android/gradle/wrapper/gradle-wrapper.properties \ - android/gradlew \ - android/gradlew.bat \ - android/gradle.properties \ - android/res/values/libs.xml \ - android/src/org/amnezia/vpn/OpenVPNThreadv3.kt \ - android/src/org/amnezia/vpn/VpnService.kt \ - android/src/org/amnezia/vpn/VpnServiceBinder.kt \ - android/src/org/amnezia/vpn/qt/VPNPermissionHelper.kt - - ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android + android/AndroidManifest.xml \ + android/build.gradle \ + android/gradle/wrapper/gradle-wrapper.jar \ + android/gradle/wrapper/gradle-wrapper.properties \ + android/gradlew \ + android/gradlew.bat \ + android/gradle.properties \ + android/res/values/libs.xml \ + android/src/org/amnezia/vpn/OpenVPNThreadv3.kt \ + android/src/org/amnezia/vpn/VpnService.kt \ + android/src/org/amnezia/vpn/VpnServiceBinder.kt \ + android/src/org/amnezia/vpn/qt/VPNPermissionHelper.kt + + ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android for (abi, ANDROID_ABIS): { equals(ANDROID_TARGET_ARCH,$$abi) { diff --git a/client/main.cpp b/client/main.cpp index 196d5cec9..904569417 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -1,54 +1,10 @@ -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include "ui/uilogic.h" #include +#include -#include "ui/pages.h" - -#include "ui/pages_logic/AppSettingsLogic.h" -#include "ui/pages_logic/GeneralSettingsLogic.h" -#include "ui/pages_logic/NetworkSettingsLogic.h" -#include "ui/pages_logic/NewServerProtocolsLogic.h" -#include "ui/pages_logic/QrDecoderLogic.h" -#include "ui/pages_logic/ServerConfiguringProgressLogic.h" -#include "ui/pages_logic/ServerContainersLogic.h" -#include "ui/pages_logic/ServerListLogic.h" -#include "ui/pages_logic/ServerSettingsLogic.h" -#include "ui/pages_logic/ServerContainersLogic.h" -#include "ui/pages_logic/ShareConnectionLogic.h" -#include "ui/pages_logic/SitesLogic.h" -#include "ui/pages_logic/StartPageLogic.h" -#include "ui/pages_logic/VpnLogic.h" -#include "ui/pages_logic/WizardLogic.h" - -#include "ui/pages_logic/protocols/CloakLogic.h" -#include "ui/pages_logic/protocols/OpenVpnLogic.h" -#include "ui/pages_logic/protocols/ShadowSocksLogic.h" - -#include "ui/uilogic.h" - -#include "QZXing.h" - -#include "platforms/ios/QRCodeReaderBase.h" -#include "platforms/ios/MobileUtils.h" - -#include "debug.h" +#include "amnezia_application.h" #include "defines.h" -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) -#define QAPPLICATION_CLASS QGuiApplication -#include "singleapplication.h" -#undef QAPPLICATION_CLASS -#endif - #ifdef Q_OS_WIN #include "Windows.h" @@ -62,26 +18,21 @@ #include "QtAppDelegate-C-Interface.h" #endif -static void loadTranslator() -{ - QTranslator* translator = new QTranslator; - if (translator->load(QLocale(), QString("amneziavpn"), QLatin1String("_"), QLatin1String(":/translations"))) { - qApp->installTranslator(translator); - } -} int main(int argc, char *argv[]) { QLoggingCategory::setFilterRules(QStringLiteral("qtc.ssh=false")); - QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true); #ifdef Q_OS_WIN AllowSetForegroundWindow(ASFW_ANY); #endif -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) - SingleApplication app(argc, argv, true, SingleApplication::Mode::User | SingleApplication::Mode::SecondaryNotification); + +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + AmneziaApplication app(argc, argv); +#else + AmneziaApplication app(argc, argv, true, SingleApplication::Mode::User | SingleApplication::Mode::SecondaryNotification); if (!app.isPrimary()) { QTimer::singleShot(1000, &app, [&](){ @@ -89,10 +40,9 @@ int main(int argc, char *argv[]) }); return app.exec(); } -#else - QApplication app(argc, argv); #endif +// Allow to raise app window if secondary instance launched #ifdef Q_OS_WIN AllowSetForegroundWindow(0); #endif @@ -105,155 +55,17 @@ int main(int argc, char *argv[]) QtAppDelegateInitialize(); #endif - loadTranslator(); - - QFontDatabase::addApplicationFont(":/fonts/Lato-Black.ttf"); - QFontDatabase::addApplicationFont(":/fonts/Lato-BlackItalic.ttf"); - QFontDatabase::addApplicationFont(":/fonts/Lato-Bold.ttf"); - QFontDatabase::addApplicationFont(":/fonts/Lato-BoldItalic.ttf"); - QFontDatabase::addApplicationFont(":/fonts/Lato-Italic.ttf"); - QFontDatabase::addApplicationFont(":/fonts/Lato-Light.ttf"); - QFontDatabase::addApplicationFont(":/fonts/Lato-LightItalic.ttf"); - QFontDatabase::addApplicationFont(":/fonts/Lato-Regular.ttf"); - QFontDatabase::addApplicationFont(":/fonts/Lato-Thin.ttf"); - QFontDatabase::addApplicationFont(":/fonts/Lato-ThinItalic.ttf"); + app.registerTypes(); app.setApplicationName(APPLICATION_NAME); app.setOrganizationName(ORGANIZATION_NAME); app.setApplicationDisplayName(APPLICATION_NAME); - QCommandLineParser parser; - parser.setApplicationDescription(APPLICATION_NAME); - parser.addHelpOption(); - parser.addVersionOption(); - - QCommandLineOption c_autostart {{"a", "autostart"}, "System autostart"}; - parser.addOption(c_autostart); - - QCommandLineOption c_cleanup {{"c", "cleanup"}, "Cleanup logs"}; - parser.addOption(c_cleanup); - - parser.process(app); - - if (parser.isSet(c_cleanup)) { - Debug::cleanUp(); - QTimer::singleShot(100,[&app]{ - app.quit(); - }); - app.exec(); - return 0; - } - - { - Settings settingsTemp; - } - - - -// MobileUtils::writeToKeychain("testKey", "12345"); -// qDebug() << "MobileUtils::readFromKeychain(\"testKey\"):" << MobileUtils::readFromKeychain("testKey"); - - Settings settings; - if (settings.isSaveLogs()) { - if (!Debug::init()) { - qWarning() << "Initialization of debug subsystem failed"; - } - } - - app.setQuitOnLastWindowClosed(false); - - QZXing::registerQMLTypes(); - - qRegisterMetaType("VpnProtocol::VpnConnectionState"); - qRegisterMetaType("ServerCredentials"); - - qRegisterMetaType("DockerContainer"); - qRegisterMetaType("TransportProto"); - qRegisterMetaType("Proto"); - qRegisterMetaType("ServiceType"); - qRegisterMetaType("Page"); - qRegisterMetaType("ConnectionState"); - - qRegisterMetaType("PageProtocolLogicBase *"); - - UiLogic *uiLogic = new UiLogic; - - QQmlApplicationEngine *engine = new QQmlApplicationEngine; - - declareQmlPageEnum(); - declareQmlProtocolEnum(); - declareQmlContainerEnum(); - - qmlRegisterType("PageType", 1, 0, "PageType"); - qmlRegisterType("QRCodeReader", 1, 0, "QRCodeReader"); - - QScopedPointer containerProps(new ContainerProps); - qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", containerProps.get()); - - QScopedPointer protocolProps(new ProtocolProps); - qmlRegisterSingletonInstance("ProtocolProps", 1, 0, "ProtocolProps", protocolProps.get()); - - const QUrl url(QStringLiteral("qrc:/ui/qml/main.qml")); - QObject::connect(engine, &QQmlApplicationEngine::objectCreated, - &app, [url](QObject *obj, const QUrl &objUrl) { - if (!obj && url == objUrl) - QCoreApplication::exit(-1); - }, Qt::QueuedConnection); - - engine->rootContext()->setContextProperty("Debug", &Debug::Instance()); - - engine->rootContext()->setContextProperty("UiLogic", uiLogic); - - engine->rootContext()->setContextProperty("AppSettingsLogic", uiLogic->appSettingsLogic()); - engine->rootContext()->setContextProperty("GeneralSettingsLogic", uiLogic->generalSettingsLogic()); - engine->rootContext()->setContextProperty("NetworkSettingsLogic", uiLogic->networkSettingsLogic()); - engine->rootContext()->setContextProperty("NewServerProtocolsLogic", uiLogic->newServerProtocolsLogic()); - engine->rootContext()->setContextProperty("QrDecoderLogic", uiLogic->qrDecoderLogic()); - engine->rootContext()->setContextProperty("ServerConfiguringProgressLogic", uiLogic->serverConfiguringProgressLogic()); - engine->rootContext()->setContextProperty("ServerListLogic", uiLogic->serverListLogic()); - engine->rootContext()->setContextProperty("ServerSettingsLogic", uiLogic->serverSettingsLogic()); - engine->rootContext()->setContextProperty("ServerContainersLogic", uiLogic->serverprotocolsLogic()); - engine->rootContext()->setContextProperty("ShareConnectionLogic", uiLogic->shareConnectionLogic()); - engine->rootContext()->setContextProperty("SitesLogic", uiLogic->sitesLogic()); - engine->rootContext()->setContextProperty("StartPageLogic", uiLogic->startPageLogic()); - engine->rootContext()->setContextProperty("VpnLogic", uiLogic->vpnLogic()); - engine->rootContext()->setContextProperty("WizardLogic", uiLogic->wizardLogic()); + app.loadTranslator(); + app.loadFonts(); -#if defined(Q_OS_IOS) - setStartPageLogic(uiLogic->startPageLogic()); -#endif - - engine->load(url); - - QObject::connect(&app, &QCoreApplication::aboutToQuit, uiLogic, [&engine, uiLogic](){ - QObject::disconnect(engine, 0,0,0); - delete engine; - - QObject::disconnect(uiLogic, 0,0,0); - delete uiLogic; - }); - - if (engine->rootObjects().size() > 0) { - uiLogic->setQmlRoot(engine->rootObjects().at(0)); - } - -#ifdef Q_OS_WIN - if (parser.isSet("a")) uiLogic->showOnStartup(); - else emit uiLogic->show(); -#else - uiLogic->showOnStartup(); -#endif - - // TODO - fix -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) - if (app.isPrimary()) { - QObject::connect(&app, &SingleApplication::instanceStarted, uiLogic, [&](){ - qDebug() << "Secondary instance started, showing this window instead"; - emit uiLogic->show(); - emit uiLogic->raise(); - }); - } -#endif + app.parseCommands(); + app.init(); return app.exec(); } diff --git a/client/settings.h b/client/settings.h index 18337f0d7..fc5753297 100644 --- a/client/settings.h +++ b/client/settings.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "core/defs.h" #include "containers/containers_defs.h" @@ -116,6 +117,7 @@ class Settings : public QObject private: SecureQSettings m_settings; + QMutex m_mutex; }; #endif // SETTINGS_H diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp index 15fc8f8d9..5468452ee 100644 --- a/client/ui/models/containers_model.cpp +++ b/client/ui/models/containers_model.cpp @@ -1,6 +1,7 @@ #include "containers_model.h" -ContainersModel::ContainersModel(QObject *parent) : +ContainersModel::ContainersModel(std::shared_ptr settings, QObject *parent) : + m_settings(settings), QAbstractListModel(parent) { @@ -37,13 +38,13 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const return ContainerProps::containerDescriptions().value(c); } if (role == DefaultRole) { - return c == m_settings.defaultContainer(m_selectedServerIndex); + return c == m_settings->defaultContainer(m_selectedServerIndex); } if (role == ServiceTypeRole) { return ContainerProps::containerService(c); } if (role == IsInstalledRole) { - return m_settings.containers(m_selectedServerIndex).contains(c); + return m_settings->containers(m_selectedServerIndex).contains(c); } return QVariant(); } diff --git a/client/ui/models/containers_model.h b/client/ui/models/containers_model.h index 479690b0a..362068557 100644 --- a/client/ui/models/containers_model.h +++ b/client/ui/models/containers_model.h @@ -13,7 +13,7 @@ class ContainersModel : public QAbstractListModel { Q_OBJECT public: - ContainersModel(QObject *parent = nullptr); + ContainersModel(std::shared_ptr settings, QObject *parent = nullptr); public: enum SiteRoles { NameRole = Qt::UserRole + 1, @@ -33,7 +33,7 @@ class ContainersModel : public QAbstractListModel private: int m_selectedServerIndex; - Settings m_settings; + std::shared_ptr m_settings; }; #endif // CONTAINERS_MODEL_H diff --git a/client/ui/models/protocols_model.cpp b/client/ui/models/protocols_model.cpp index 76e5c6234..7359bb364 100644 --- a/client/ui/models/protocols_model.cpp +++ b/client/ui/models/protocols_model.cpp @@ -1,6 +1,7 @@ #include "protocols_model.h" -ProtocolsModel::ProtocolsModel(QObject *parent) : +ProtocolsModel::ProtocolsModel(std::shared_ptr settings, QObject *parent) : + m_settings(settings), QAbstractListModel(parent) { diff --git a/client/ui/models/protocols_model.h b/client/ui/models/protocols_model.h index bd2715587..48b6eeb64 100644 --- a/client/ui/models/protocols_model.h +++ b/client/ui/models/protocols_model.h @@ -13,7 +13,7 @@ class ProtocolsModel : public QAbstractListModel { Q_OBJECT public: - ProtocolsModel(QObject *parent = nullptr); + ProtocolsModel(std::shared_ptr settings, QObject *parent = nullptr); public: enum SiteRoles { NameRole = Qt::UserRole + 1, @@ -34,7 +34,7 @@ class ProtocolsModel : public QAbstractListModel private: int m_selectedServerIndex; DockerContainer m_selectedDockerContainer; - Settings m_settings; + std::shared_ptr m_settings; }; #endif // PROTOCOLS_MODEL_H diff --git a/client/ui/models/sites_model.cpp b/client/ui/models/sites_model.cpp index 9fc5452d4..fe0f4ccf3 100644 --- a/client/ui/models/sites_model.cpp +++ b/client/ui/models/sites_model.cpp @@ -1,7 +1,8 @@ #include "sites_model.h" -SitesModel::SitesModel(Settings::RouteMode mode, QObject *parent) +SitesModel::SitesModel(std::shared_ptr settings, Settings::RouteMode mode, QObject *parent) : QAbstractListModel(parent), + m_settings(settings), m_mode(mode) { } @@ -68,7 +69,7 @@ void SitesModel::genCache() const qDebug() << "SitesModel::genCache"; m_ipsCache.clear(); - const QVariantMap &sites = m_settings.vpnSites(m_mode); + const QVariantMap &sites = m_settings->vpnSites(m_mode); auto i = sites.constBegin(); while (i != sites.constEnd()) { m_ipsCache.append(qMakePair(i.key(), i.value().toString())); diff --git a/client/ui/models/sites_model.h b/client/ui/models/sites_model.h index 5e4feb0f5..7bf04b508 100644 --- a/client/ui/models/sites_model.h +++ b/client/ui/models/sites_model.h @@ -15,7 +15,7 @@ class SitesModel : public QAbstractListModel IpRole }; - explicit SitesModel(Settings::RouteMode mode, QObject *parent = nullptr); + explicit SitesModel(std::shared_ptr settings, Settings::RouteMode mode, QObject *parent = nullptr); void resetCache(); // Basic functionality: @@ -32,7 +32,7 @@ class SitesModel : public QAbstractListModel private: Settings::RouteMode m_mode; - Settings m_settings; + std::shared_ptr m_settings; mutable QVector> m_ipsCache; mutable bool m_cacheReady = false; diff --git a/client/ui/pages_logic/AppSettingsLogic.cpp b/client/ui/pages_logic/AppSettingsLogic.cpp index ccdb5071c..e9c614aad 100644 --- a/client/ui/pages_logic/AppSettingsLogic.cpp +++ b/client/ui/pages_logic/AppSettingsLogic.cpp @@ -25,9 +25,9 @@ AppSettingsLogic::AppSettingsLogic(UiLogic *logic, QObject *parent): void AppSettingsLogic::onUpdatePage() { set_checkBoxAutostartChecked(Autostart::isAutostart()); - set_checkBoxAutoConnectChecked(m_settings.isAutoConnect()); - set_checkBoxStartMinimizedChecked(m_settings.isStartMinimized()); - set_checkBoxSaveLogsChecked(m_settings.isSaveLogs()); + set_checkBoxAutoConnectChecked(m_settings->isAutoConnect()); + set_checkBoxStartMinimizedChecked(m_settings->isStartMinimized()); + set_checkBoxSaveLogsChecked(m_settings->isSaveLogs()); QString ver = QString("%1: %2 (%3)") .arg(tr("Software version")) @@ -46,17 +46,17 @@ void AppSettingsLogic::onCheckBoxAutostartToggled(bool checked) void AppSettingsLogic::onCheckBoxAutoconnectToggled(bool checked) { - m_settings.setAutoConnect(checked); + m_settings->setAutoConnect(checked); } void AppSettingsLogic::onCheckBoxStartMinimizedToggled(bool checked) { - m_settings.setStartMinimized(checked); + m_settings->setStartMinimized(checked); } void AppSettingsLogic::onCheckBoxSaveLogsCheckedToggled(bool checked) { - m_settings.setSaveLogs(checked); + m_settings->setSaveLogs(checked); } void AppSettingsLogic::onPushButtonOpenLogsClicked() @@ -77,7 +77,7 @@ void AppSettingsLogic::onPushButtonClearLogsClicked() void AppSettingsLogic::onPushButtonBackupAppConfigClicked() { - uiLogic()->saveTextFile("Backup application config", "AmneziaVPN.backup", ".backup", m_settings.backupAppConfig()); + uiLogic()->saveTextFile("Backup application config", "AmneziaVPN.backup", ".backup", m_settings->backupAppConfig()); } void AppSettingsLogic::onPushButtonRestoreAppConfigClicked() @@ -91,7 +91,7 @@ void AppSettingsLogic::onPushButtonRestoreAppConfigClicked() file.open(QIODevice::ReadOnly); QByteArray data = file.readAll(); - m_settings.restoreAppConfig(data); + m_settings->restoreAppConfig(data); emit uiLogic()->goToPage(Page::Vpn); emit uiLogic()->setStartPage(Page::Vpn); diff --git a/client/ui/pages_logic/GeneralSettingsLogic.cpp b/client/ui/pages_logic/GeneralSettingsLogic.cpp index 92696afaa..344fd5fad 100644 --- a/client/ui/pages_logic/GeneralSettingsLogic.cpp +++ b/client/ui/pages_logic/GeneralSettingsLogic.cpp @@ -12,24 +12,24 @@ GeneralSettingsLogic::GeneralSettingsLogic(UiLogic *logic, QObject *parent): void GeneralSettingsLogic::onUpdatePage() { - uiLogic()->selectedServerIndex = m_settings.defaultServerIndex(); - uiLogic()->selectedDockerContainer = m_settings.defaultContainer(m_settings.defaultServerIndex()); + uiLogic()->selectedServerIndex = m_settings->defaultServerIndex(); + uiLogic()->selectedDockerContainer = m_settings->defaultContainer(m_settings->defaultServerIndex()); - set_pushButtonGeneralSettingsShareConnectionEnable(m_settings.haveAuthData(m_settings.defaultServerIndex())); + set_pushButtonGeneralSettingsShareConnectionEnable(m_settings->haveAuthData(m_settings->defaultServerIndex())); } void GeneralSettingsLogic::onPushButtonGeneralSettingsServerSettingsClicked() { - uiLogic()->selectedServerIndex = m_settings.defaultServerIndex(); - uiLogic()->selectedDockerContainer = m_settings.defaultContainer(m_settings.defaultServerIndex()); + uiLogic()->selectedServerIndex = m_settings->defaultServerIndex(); + uiLogic()->selectedDockerContainer = m_settings->defaultContainer(m_settings->defaultServerIndex()); emit uiLogic()->goToPage(Page::ServerSettings); } void GeneralSettingsLogic::onPushButtonGeneralSettingsShareConnectionClicked() { - uiLogic()->selectedServerIndex = m_settings.defaultServerIndex(); - uiLogic()->selectedDockerContainer = m_settings.defaultContainer(uiLogic()->selectedServerIndex); + uiLogic()->selectedServerIndex = m_settings->defaultServerIndex(); + uiLogic()->selectedDockerContainer = m_settings->defaultContainer(uiLogic()->selectedServerIndex); qobject_cast(uiLogic()->protocolsModel())->setSelectedServerIndex(uiLogic()->selectedServerIndex); qobject_cast(uiLogic()->protocolsModel())->setSelectedDockerContainer(uiLogic()->selectedDockerContainer); diff --git a/client/ui/pages_logic/NetworkSettingsLogic.cpp b/client/ui/pages_logic/NetworkSettingsLogic.cpp index bd593e3a9..f7e77378e 100644 --- a/client/ui/pages_logic/NetworkSettingsLogic.cpp +++ b/client/ui/pages_logic/NetworkSettingsLogic.cpp @@ -13,39 +13,39 @@ NetworkSettingsLogic::NetworkSettingsLogic(UiLogic *logic, QObject *parent): void NetworkSettingsLogic::onUpdatePage() { - set_checkBoxUseAmneziaDnsChecked(m_settings.useAmneziaDns()); + set_checkBoxUseAmneziaDnsChecked(m_settings->useAmneziaDns()); - set_lineEditDns1Text(m_settings.primaryDns()); - set_lineEditDns2Text(m_settings.secondaryDns()); + set_lineEditDns1Text(m_settings->primaryDns()); + set_lineEditDns2Text(m_settings->secondaryDns()); } void NetworkSettingsLogic::onLineEditDns1EditFinished(const QString &text) { if (ipAddressRegex().exactMatch(text)) { - m_settings.setPrimaryDns(text); + m_settings->setPrimaryDns(text); } } void NetworkSettingsLogic::onLineEditDns2EditFinished(const QString &text) { if (ipAddressRegex().exactMatch(text)) { - m_settings.setSecondaryDns(text); + m_settings->setSecondaryDns(text); } } void NetworkSettingsLogic::onPushButtonResetDns1Clicked() { - m_settings.setPrimaryDns(m_settings.cloudFlareNs1); + m_settings->setPrimaryDns(m_settings->cloudFlareNs1); onUpdatePage(); } void NetworkSettingsLogic::onPushButtonResetDns2Clicked() { - m_settings.setSecondaryDns(m_settings.cloudFlareNs2); + m_settings->setSecondaryDns(m_settings->cloudFlareNs2); onUpdatePage(); } void NetworkSettingsLogic::onCheckBoxUseAmneziaDnsToggled(bool checked) { - m_settings.setUseAmneziaDns(checked); + m_settings->setUseAmneziaDns(checked); } diff --git a/client/ui/pages_logic/PageLogicBase.cpp b/client/ui/pages_logic/PageLogicBase.cpp index f06382136..78fd15d78 100644 --- a/client/ui/pages_logic/PageLogicBase.cpp +++ b/client/ui/pages_logic/PageLogicBase.cpp @@ -1,4 +1,5 @@ #include "PageLogicBase.h" +#include "ui/uilogic.h" PageLogicBase::PageLogicBase(UiLogic *logic, QObject *parent): @@ -6,6 +7,7 @@ PageLogicBase::PageLogicBase(UiLogic *logic, QObject *parent): m_pageEnabled{true}, m_uiLogic(logic) { - + m_settings = logic->m_settings; } + diff --git a/client/ui/pages_logic/PageLogicBase.h b/client/ui/pages_logic/PageLogicBase.h index 26858ee09..22df01349 100644 --- a/client/ui/pages_logic/PageLogicBase.h +++ b/client/ui/pages_logic/PageLogicBase.h @@ -23,8 +23,8 @@ class PageLogicBase : public QObject protected: UiLogic *uiLogic() const { return m_uiLogic; } + std::shared_ptr m_settings; - Settings m_settings; UiLogic *m_uiLogic; signals: diff --git a/client/ui/pages_logic/ServerContainersLogic.cpp b/client/ui/pages_logic/ServerContainersLogic.cpp index e01e1bac9..8822ed922 100644 --- a/client/ui/pages_logic/ServerContainersLogic.cpp +++ b/client/ui/pages_logic/ServerContainersLogic.cpp @@ -36,21 +36,21 @@ void ServerContainersLogic::onPushButtonProtoSettingsClicked(DockerContainer c, { qDebug()<< "ServerContainersLogic::onPushButtonProtoSettingsClicked" << c << p; uiLogic()->selectedDockerContainer = c; - uiLogic()->protocolLogic(p)->updateProtocolPage(m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, p), + uiLogic()->protocolLogic(p)->updateProtocolPage(m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, p), uiLogic()->selectedDockerContainer, - m_settings.haveAuthData(uiLogic()->selectedServerIndex)); + m_settings->haveAuthData(uiLogic()->selectedServerIndex)); emit uiLogic()->goToProtocolPage(p); } void ServerContainersLogic::onPushButtonDefaultClicked(DockerContainer c) { - if (m_settings.defaultContainer(uiLogic()->selectedServerIndex) == c) return; + if (m_settings->defaultContainer(uiLogic()->selectedServerIndex) == c) return; - m_settings.setDefaultContainer(uiLogic()->selectedServerIndex, c); + m_settings->setDefaultContainer(uiLogic()->selectedServerIndex, c); uiLogic()->onUpdateAllPages(); - if (uiLogic()->selectedServerIndex != m_settings.defaultServerIndex()) return; + if (uiLogic()->selectedServerIndex != m_settings->defaultServerIndex()) return; if (!uiLogic()->m_vpnConnection) return; if (!uiLogic()->m_vpnConnection->isConnected()) return; @@ -67,14 +67,14 @@ void ServerContainersLogic::onPushButtonShareClicked(DockerContainer c) void ServerContainersLogic::onPushButtonRemoveClicked(DockerContainer container) { //buttonSetEnabledFunc(false); - ErrorCode e = ServerController::removeContainer(m_settings.serverCredentials(uiLogic()->selectedServerIndex), container); - m_settings.removeContainerConfig(uiLogic()->selectedServerIndex, container); + ErrorCode e = ServerController::removeContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), container); + m_settings->removeContainerConfig(uiLogic()->selectedServerIndex, container); //buttonSetEnabledFunc(true); - if (m_settings.defaultContainer(uiLogic()->selectedServerIndex) == container) { - const auto &c = m_settings.containers(uiLogic()->selectedServerIndex); - if (c.isEmpty()) m_settings.setDefaultContainer(uiLogic()->selectedServerIndex, DockerContainer::None); - else m_settings.setDefaultContainer(uiLogic()->selectedServerIndex, c.keys().first()); + if (m_settings->defaultContainer(uiLogic()->selectedServerIndex) == container) { + const auto &c = m_settings->containers(uiLogic()->selectedServerIndex); + if (c.isEmpty()) m_settings->setDefaultContainer(uiLogic()->selectedServerIndex, DockerContainer::None); + else m_settings->setDefaultContainer(uiLogic()->selectedServerIndex, c.keys().first()); } uiLogic()->onUpdateAllPages(); } @@ -87,13 +87,13 @@ void ServerContainersLogic::onPushButtonContinueClicked(DockerContainer c, int p qApp->processEvents(); ErrorCode e = uiLogic()->serverConfiguringProgressLogic()->doInstallAction([this, c, &config](){ - return ServerController::setupContainer(m_settings.serverCredentials(uiLogic()->selectedServerIndex), c, config); + return ServerController::setupContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), c, config); }); if (!e) { - m_settings.setContainerConfig(uiLogic()->selectedServerIndex, c, config); + m_settings->setContainerConfig(uiLogic()->selectedServerIndex, c, config); if (ContainerProps::containerService(c) == ServiceType::Vpn) { - m_settings.setDefaultContainer(uiLogic()->selectedServerIndex, c); + m_settings->setDefaultContainer(uiLogic()->selectedServerIndex, c); } } diff --git a/client/ui/pages_logic/ServerListLogic.cpp b/client/ui/pages_logic/ServerListLogic.cpp index 05cac928a..fe3f6512f 100644 --- a/client/ui/pages_logic/ServerListLogic.cpp +++ b/client/ui/pages_logic/ServerListLogic.cpp @@ -13,7 +13,7 @@ ServerListLogic::ServerListLogic(UiLogic *logic, QObject *parent): void ServerListLogic::onServerListPushbuttonDefaultClicked(int index) { - m_settings.setDefaultServer(index); + m_settings->setDefaultServer(index); uiLogic()->onUpdateAllPages(); } @@ -25,8 +25,8 @@ void ServerListLogic::onServerListPushbuttonSettingsClicked(int index) void ServerListLogic::onUpdatePage() { - const QJsonArray &servers = m_settings.serversArray(); - int defaultServer = m_settings.defaultServerIndex(); + const QJsonArray &servers = m_settings->serversArray(); + int defaultServer = m_settings->defaultServerIndex(); std::vector serverListContent; for(int i = 0; i < servers.size(); i++) { ServerModelContent c; diff --git a/client/ui/pages_logic/ServerSettingsLogic.cpp b/client/ui/pages_logic/ServerSettingsLogic.cpp index e15207b74..e23660fae 100644 --- a/client/ui/pages_logic/ServerSettingsLogic.cpp +++ b/client/ui/pages_logic/ServerSettingsLogic.cpp @@ -26,10 +26,10 @@ void ServerSettingsLogic::onUpdatePage() { set_labelWaitInfoVisible(false); set_labelWaitInfoText(""); - set_pushButtonClearVisible(m_settings.haveAuthData(uiLogic()->selectedServerIndex)); - set_pushButtonClearClientCacheVisible(m_settings.haveAuthData(uiLogic()->selectedServerIndex)); - set_pushButtonShareFullVisible(m_settings.haveAuthData(uiLogic()->selectedServerIndex)); - const QJsonObject &server = m_settings.server(uiLogic()->selectedServerIndex); + set_pushButtonClearVisible(m_settings->haveAuthData(uiLogic()->selectedServerIndex)); + set_pushButtonClearClientCacheVisible(m_settings->haveAuthData(uiLogic()->selectedServerIndex)); + set_pushButtonShareFullVisible(m_settings->haveAuthData(uiLogic()->selectedServerIndex)); + const QJsonObject &server = m_settings->server(uiLogic()->selectedServerIndex); const QString &port = server.value(config_key::port).toString(); set_labelServerText(QString("%1@%2%3%4") .arg(server.value(config_key::userName).toString()) @@ -38,7 +38,7 @@ void ServerSettingsLogic::onUpdatePage() .arg(port)); set_lineEditDescriptionText(server.value(config_key::description).toString()); - DockerContainer selectedContainer = m_settings.defaultContainer(uiLogic()->selectedServerIndex); + DockerContainer selectedContainer = m_settings->defaultContainer(uiLogic()->selectedServerIndex); QString selectedContainerName = ContainerProps::containerHumanNames().value(selectedContainer); set_labelCurrentVpnProtocolText(tr("Service: ") + selectedContainerName); } @@ -48,12 +48,12 @@ void ServerSettingsLogic::onPushButtonClearServer() set_pageEnabled(false); set_pushButtonClearText(tr("Uninstalling Amnezia software...")); - if (m_settings.defaultServerIndex() == uiLogic()->selectedServerIndex) { + if (m_settings->defaultServerIndex() == uiLogic()->selectedServerIndex) { uiLogic()->vpnLogic()->onDisconnect(); } - ErrorCode e = ServerController::removeAllContainers(m_settings.serverCredentials(uiLogic()->selectedServerIndex)); - ServerController::disconnectFromHost(m_settings.serverCredentials(uiLogic()->selectedServerIndex)); + ErrorCode e = ServerController::removeAllContainers(m_settings->serverCredentials(uiLogic()->selectedServerIndex)); + ServerController::disconnectFromHost(m_settings->serverCredentials(uiLogic()->selectedServerIndex)); if (e) { uiLogic()->setDialogConnectErrorText( tr("Error occurred while configuring server.") + "\n" + @@ -66,8 +66,8 @@ void ServerSettingsLogic::onPushButtonClearServer() set_labelWaitInfoText(tr("Amnezia server successfully uninstalled")); } - m_settings.setContainers(uiLogic()->selectedServerIndex, {}); - m_settings.setDefaultContainer(uiLogic()->selectedServerIndex, DockerContainer::None); + m_settings->setContainers(uiLogic()->selectedServerIndex, {}); + m_settings->setDefaultContainer(uiLogic()->selectedServerIndex, DockerContainer::None); set_pageEnabled(true); set_pushButtonClearText(tr("Clear server from Amnezia software")); @@ -75,27 +75,27 @@ void ServerSettingsLogic::onPushButtonClearServer() void ServerSettingsLogic::onPushButtonForgetServer() { - if (m_settings.defaultServerIndex() == uiLogic()->selectedServerIndex && uiLogic()->m_vpnConnection->isConnected()) { + if (m_settings->defaultServerIndex() == uiLogic()->selectedServerIndex && uiLogic()->m_vpnConnection->isConnected()) { uiLogic()->vpnLogic()->onDisconnect(); } - m_settings.removeServer(uiLogic()->selectedServerIndex); + m_settings->removeServer(uiLogic()->selectedServerIndex); - if (m_settings.defaultServerIndex() == uiLogic()->selectedServerIndex) { - m_settings.setDefaultServer(0); + if (m_settings->defaultServerIndex() == uiLogic()->selectedServerIndex) { + m_settings->setDefaultServer(0); } - else if (m_settings.defaultServerIndex() > uiLogic()->selectedServerIndex) { - m_settings.setDefaultServer(m_settings.defaultServerIndex() - 1); + else if (m_settings->defaultServerIndex() > uiLogic()->selectedServerIndex) { + m_settings->setDefaultServer(m_settings->defaultServerIndex() - 1); } - if (m_settings.serversCount() == 0) { - m_settings.setDefaultServer(-1); + if (m_settings->serversCount() == 0) { + m_settings->setDefaultServer(-1); } uiLogic()->selectedServerIndex = -1; uiLogic()->onUpdateAllPages(); - if (m_settings.serversCount() == 0) { + if (m_settings->serversCount() == 0) { uiLogic()->setStartPage(Page::Start); } else { @@ -107,9 +107,9 @@ void ServerSettingsLogic::onPushButtonClearClientCacheClicked() { set_pushButtonClearClientCacheText(tr("Cache cleared")); - const auto &containers = m_settings.containers(uiLogic()->selectedServerIndex); + const auto &containers = m_settings->containers(uiLogic()->selectedServerIndex); for (DockerContainer container: containers.keys()) { - m_settings.clearLastConnectionConfig(uiLogic()->selectedServerIndex, container); + m_settings->clearLastConnectionConfig(uiLogic()->selectedServerIndex, container); } QTimer::singleShot(3000, this, [this]() { @@ -120,9 +120,9 @@ void ServerSettingsLogic::onPushButtonClearClientCacheClicked() void ServerSettingsLogic::onLineEditDescriptionEditingFinished() { const QString &newText = lineEditDescriptionText(); - QJsonObject server = m_settings.server(uiLogic()->selectedServerIndex); + QJsonObject server = m_settings->server(uiLogic()->selectedServerIndex); server.insert(config_key::description, newText); - m_settings.editServer(uiLogic()->selectedServerIndex, server); + m_settings->editServer(uiLogic()->selectedServerIndex, server); uiLogic()->onUpdateAllPages(); } diff --git a/client/ui/pages_logic/ShareConnectionLogic.cpp b/client/ui/pages_logic/ShareConnectionLogic.cpp index 038b38919..1b042a295 100644 --- a/client/ui/pages_logic/ShareConnectionLogic.cpp +++ b/client/ui/pages_logic/ShareConnectionLogic.cpp @@ -73,17 +73,17 @@ void ShareConnectionLogic::onPushButtonShareAmneziaGenerateClicked() // Full access if (shareFullAccess()) { - serverConfig = m_settings.server(serverIndex); + serverConfig = m_settings->server(serverIndex); } // Container share else { - ServerCredentials credentials = m_settings.serverCredentials(serverIndex); - QJsonObject containerConfig = m_settings.containerConfig(serverIndex, container); + ServerCredentials credentials = m_settings->serverCredentials(serverIndex); + QJsonObject containerConfig = m_settings->containerConfig(serverIndex, container); containerConfig.insert(config_key::container, ContainerProps::containerToString(container)); ErrorCode e = ErrorCode::NoError; for (Proto p: ContainerProps::protocolsForContainer(container)) { - QJsonObject protoConfig = m_settings.protocolConfig(serverIndex, container, p); + QJsonObject protoConfig = m_settings->protocolConfig(serverIndex, container, p); QString cfg = VpnConfigurator::genVpnProtocolConfig(credentials, container, containerConfig, p, &e); if (e) { @@ -96,7 +96,7 @@ void ShareConnectionLogic::onPushButtonShareAmneziaGenerateClicked() QByteArray ba; if (!e) { - serverConfig = m_settings.server(serverIndex); + serverConfig = m_settings->server(serverIndex); serverConfig.remove(config_key::userName); serverConfig.remove(config_key::password); serverConfig.remove(config_key::port); @@ -129,9 +129,9 @@ void ShareConnectionLogic::onPushButtonShareOpenVpnGenerateClicked() { int serverIndex = uiLogic()->selectedServerIndex; DockerContainer container = uiLogic()->selectedDockerContainer; - ServerCredentials credentials = m_settings.serverCredentials(serverIndex); + ServerCredentials credentials = m_settings->serverCredentials(serverIndex); - const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container); + const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container); ErrorCode e = ErrorCode::NoError; QString cfg = OpenVpnConfigurator::genOpenVpnConfig(credentials, container, containerConfig, &e); @@ -144,13 +144,13 @@ void ShareConnectionLogic::onPushButtonShareShadowSocksGenerateClicked() { int serverIndex = uiLogic()->selectedServerIndex; DockerContainer container = uiLogic()->selectedDockerContainer; - ServerCredentials credentials = m_settings.serverCredentials(serverIndex); + ServerCredentials credentials = m_settings->serverCredentials(serverIndex); - QJsonObject protoConfig = m_settings.protocolConfig(serverIndex, container, Proto::ShadowSocks); + QJsonObject protoConfig = m_settings->protocolConfig(serverIndex, container, Proto::ShadowSocks); QString cfg = protoConfig.value(config_key::last_config).toString(); if (cfg.isEmpty()) { - const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container); + const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container); ErrorCode e = ErrorCode::NoError; cfg = ShadowSocksConfigurator::genShadowSocksConfig(credentials, container, containerConfig, &e); @@ -186,13 +186,13 @@ void ShareConnectionLogic::onPushButtonShareCloakGenerateClicked() { int serverIndex = uiLogic()->selectedServerIndex; DockerContainer container = uiLogic()->selectedDockerContainer; - ServerCredentials credentials = m_settings.serverCredentials(serverIndex); + ServerCredentials credentials = m_settings->serverCredentials(serverIndex); - QJsonObject protoConfig = m_settings.protocolConfig(serverIndex, container, Proto::Cloak); + QJsonObject protoConfig = m_settings->protocolConfig(serverIndex, container, Proto::Cloak); QString cfg = protoConfig.value(config_key::last_config).toString(); if (cfg.isEmpty()) { - const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container); + const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container); ErrorCode e = ErrorCode::NoError; cfg = CloakConfigurator::genCloakConfig(credentials, container, containerConfig, &e); @@ -209,9 +209,9 @@ void ShareConnectionLogic::onPushButtonShareWireGuardGenerateClicked() { int serverIndex = uiLogic()->selectedServerIndex; DockerContainer container = uiLogic()->selectedDockerContainer; - ServerCredentials credentials = m_settings.serverCredentials(serverIndex); + ServerCredentials credentials = m_settings->serverCredentials(serverIndex); - const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container); + const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container); ErrorCode e = ErrorCode::NoError; QString cfg = WireguardConfigurator::genWireguardConfig(credentials, container, containerConfig, &e); @@ -235,9 +235,9 @@ void ShareConnectionLogic::onPushButtonShareIkev2GenerateClicked() { int serverIndex = uiLogic()->selectedServerIndex; DockerContainer container = uiLogic()->selectedDockerContainer; - ServerCredentials credentials = m_settings.serverCredentials(serverIndex); + ServerCredentials credentials = m_settings->serverCredentials(serverIndex); - //const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container); + //const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container); Ikev2Configurator::ConnectionData connData = Ikev2Configurator::prepareIkev2Config(credentials, container); diff --git a/client/ui/pages_logic/SitesLogic.cpp b/client/ui/pages_logic/SitesLogic.cpp index 8b94155f4..e9966bfaf 100644 --- a/client/ui/pages_logic/SitesLogic.cpp +++ b/client/ui/pages_logic/SitesLogic.cpp @@ -18,13 +18,13 @@ SitesLogic::SitesLogic(UiLogic *logic, QObject *parent): m_tableViewSitesModel{nullptr}, m_lineEditSitesAddCustomText{} { - sitesModels.insert(Settings::VpnOnlyForwardSites, new SitesModel(Settings::VpnOnlyForwardSites)); - sitesModels.insert(Settings::VpnAllExceptSites, new SitesModel(Settings::VpnAllExceptSites)); + sitesModels.insert(Settings::VpnOnlyForwardSites, new SitesModel(m_settings, Settings::VpnOnlyForwardSites)); + sitesModels.insert(Settings::VpnAllExceptSites, new SitesModel(m_settings, Settings::VpnAllExceptSites)); } void SitesLogic::onUpdatePage() { - Settings::RouteMode m = m_settings.routeMode(); + Settings::RouteMode m = m_settings->routeMode(); if (m == Settings::VpnAllSites) return; if (m == Settings::VpnOnlyForwardSites) { @@ -43,7 +43,7 @@ void SitesLogic::onPushButtonAddCustomSitesClicked() if (uiLogic()->vpnLogic()->radioButtonVpnModeAllSitesChecked()) { return; } - Settings::RouteMode mode = m_settings.routeMode(); + Settings::RouteMode mode = m_settings->routeMode(); QString newSite = lineEditSitesAddCustomText(); @@ -60,7 +60,7 @@ void SitesLogic::onPushButtonAddCustomSitesClicked() } const auto &cbProcess = [this, mode](const QString &newSite, const QString &ip) { - m_settings.addVpnSite(mode, newSite, ip); + m_settings->addVpnSite(mode, newSite, ip); if (!ip.isEmpty()) { uiLogic()->m_vpnConnection->addRoutes(QStringList() << ip); @@ -100,7 +100,7 @@ void SitesLogic::onPushButtonAddCustomSitesClicked() void SitesLogic::onPushButtonSitesDeleteClicked(QStringList items) { - Settings::RouteMode mode = m_settings.routeMode(); + Settings::RouteMode mode = m_settings->routeMode(); auto siteModel = qobject_cast (tableViewSitesModel()); if (!siteModel || items.isEmpty()) { @@ -121,7 +121,7 @@ void SitesLogic::onPushButtonSitesDeleteClicked(QStringList items) } } - m_settings.removeVpnSites(mode, sites); + m_settings->removeVpnSites(mode, sites); if (uiLogic()->m_vpnConnection->connectionState() == VpnProtocol::Connected) { uiLogic()->m_vpnConnection->deleteRoutes(ips); @@ -139,7 +139,7 @@ void SitesLogic::onPushButtonSitesImportClicked(const QString& fileName) return; } - Settings::RouteMode mode = m_settings.routeMode(); + Settings::RouteMode mode = m_settings->routeMode(); QStringList ips; QMap sites; @@ -187,8 +187,8 @@ void SitesLogic::onPushButtonSitesImportClicked(const QString& fileName) } - m_settings.addVpnIps(mode, ips); - m_settings.addVpnSites(mode, sites); + m_settings->addVpnIps(mode, ips); + m_settings->addVpnSites(mode, sites); uiLogic()->m_vpnConnection->addRoutes(QStringList() << ips); uiLogic()->m_vpnConnection->flushDns(); @@ -198,9 +198,9 @@ void SitesLogic::onPushButtonSitesImportClicked(const QString& fileName) void SitesLogic::onPushButtonSitesExportClicked() { - Settings::RouteMode mode = m_settings.routeMode(); + Settings::RouteMode mode = m_settings->routeMode(); - QVariantMap sites = m_settings.vpnSites(mode); + QVariantMap sites = m_settings->vpnSites(mode); QString data; for (auto s : sites.keys()) { diff --git a/client/ui/pages_logic/StartPageLogic.cpp b/client/ui/pages_logic/StartPageLogic.cpp index c21aa6f62..2dd8ef626 100644 --- a/client/ui/pages_logic/StartPageLogic.cpp +++ b/client/ui/pages_logic/StartPageLogic.cpp @@ -159,8 +159,8 @@ bool StartPageLogic::importConnection(const QJsonObject &profile) //qDebug() << QString("Password") << credentials.password; if (credentials.isValid() || profile.contains(config_key::containers)) { - m_settings.addServer(profile); - m_settings.setDefaultServer(m_settings.serversCount() - 1); + m_settings->addServer(profile); + m_settings->setDefaultServer(m_settings->serversCount() - 1); emit uiLogic()->goToPage(Page::Vpn); emit uiLogic()->setStartPage(Page::Vpn); @@ -172,8 +172,8 @@ bool StartPageLogic::importConnection(const QJsonObject &profile) } if (!profile.contains(config_key::containers)) { - uiLogic()->selectedServerIndex = m_settings.defaultServerIndex(); - uiLogic()->selectedDockerContainer = m_settings.defaultContainer(uiLogic()->selectedServerIndex); + uiLogic()->selectedServerIndex = m_settings->defaultServerIndex(); + uiLogic()->selectedDockerContainer = m_settings->defaultContainer(uiLogic()->selectedServerIndex); uiLogic()->onUpdateAllPages(); emit uiLogic()->goToPage(Page::ServerContainers); diff --git a/client/ui/pages_logic/VpnLogic.cpp b/client/ui/pages_logic/VpnLogic.cpp index 5812441e8..1bfd230ca 100644 --- a/client/ui/pages_logic/VpnLogic.cpp +++ b/client/ui/pages_logic/VpnLogic.cpp @@ -33,7 +33,7 @@ VpnLogic::VpnLogic(UiLogic *logic, QObject *parent): connect(this, &VpnLogic::connectToVpn, uiLogic()->m_vpnConnection, &VpnConnection::connectToVpn, Qt::QueuedConnection); connect(this, &VpnLogic::disconnectFromVpn, uiLogic()->m_vpnConnection, &VpnConnection::disconnectFromVpn, Qt::QueuedConnection); - if (m_settings.isAutoConnect() && m_settings.defaultServerIndex() >= 0) { + if (m_settings->isAutoConnect() && m_settings->defaultServerIndex() >= 0) { QTimer::singleShot(1000, this, [this](){ set_pushButtonConnectEnabled(false); onConnect(); @@ -47,20 +47,20 @@ VpnLogic::VpnLogic(UiLogic *logic, QObject *parent): void VpnLogic::onUpdatePage() { - Settings::RouteMode mode = m_settings.routeMode(); - DockerContainer selectedContainer = m_settings.defaultContainer(m_settings.defaultServerIndex()); + Settings::RouteMode mode = m_settings->routeMode(); + DockerContainer selectedContainer = m_settings->defaultContainer(m_settings->defaultServerIndex()); set_isCustomRoutesSupported (selectedContainer == DockerContainer::OpenVpn || selectedContainer == DockerContainer::ShadowSocks|| selectedContainer == DockerContainer::Cloak); - set_isContainerHaveAuthData(m_settings.haveAuthData(m_settings.defaultServerIndex())); + set_isContainerHaveAuthData(m_settings->haveAuthData(m_settings->defaultServerIndex())); set_radioButtonVpnModeAllSitesChecked(mode == Settings::VpnAllSites || !isCustomRoutesSupported()); set_radioButtonVpnModeForwardSitesChecked(mode == Settings::VpnOnlyForwardSites && isCustomRoutesSupported()); set_radioButtonVpnModeExceptSitesChecked(mode == Settings::VpnAllExceptSites && isCustomRoutesSupported()); - const QJsonObject &server = uiLogic()->m_settings.defaultServer(); + const QJsonObject &server = uiLogic()->m_settings->defaultServer(); QString serverString = QString("%2 (%3)") .arg(server.value(config_key::description).toString()) .arg(server.value(config_key::hostName).toString()); @@ -69,7 +69,7 @@ void VpnLogic::onUpdatePage() QString selectedContainerName = ContainerProps::containerHumanNames().value(selectedContainer); set_labelCurrentService(selectedContainerName); - auto dns = VpnConfigurator::getDnsForConfig(m_settings.defaultServerIndex()); + auto dns = VpnConfigurator::getDnsForConfig(m_settings->defaultServerIndex()); set_amneziaDnsEnabled(dns.first == protocols::dns::amneziaDnsIp); if (dns.first == protocols::dns::amneziaDnsIp) { set_labelCurrentDns("On your server"); @@ -93,19 +93,19 @@ void VpnLogic::onUpdatePage() void VpnLogic::onRadioButtonVpnModeAllSitesClicked() { - m_settings.setRouteMode(Settings::VpnAllSites); + m_settings->setRouteMode(Settings::VpnAllSites); onUpdatePage(); } void VpnLogic::onRadioButtonVpnModeForwardSitesClicked() { - m_settings.setRouteMode(Settings::VpnOnlyForwardSites); + m_settings->setRouteMode(Settings::VpnOnlyForwardSites); onUpdatePage(); } void VpnLogic::onRadioButtonVpnModeExceptSitesClicked() { - m_settings.setRouteMode(Settings::VpnAllExceptSites); + m_settings->setRouteMode(Settings::VpnAllExceptSites); onUpdatePage(); } @@ -203,11 +203,11 @@ void VpnLogic::onPushButtonConnectClicked() void VpnLogic::onConnect() { - int serverIndex = m_settings.defaultServerIndex(); - ServerCredentials credentials = m_settings.serverCredentials(serverIndex); - DockerContainer container = m_settings.defaultContainer(serverIndex); + int serverIndex = m_settings->defaultServerIndex(); + ServerCredentials credentials = m_settings->serverCredentials(serverIndex); + DockerContainer container = m_settings->defaultContainer(serverIndex); - if (m_settings.containers(serverIndex).isEmpty()) { + if (m_settings->containers(serverIndex).isEmpty()) { set_labelErrorText(tr("VPN Protocols is not installed.\n Please install VPN container at first")); set_pushButtonConnectChecked(false); return; @@ -220,7 +220,7 @@ void VpnLogic::onConnect() } - const QJsonObject &containerConfig = m_settings.containerConfig(serverIndex, container); + const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container); onConnectWorker(serverIndex, credentials, container, containerConfig); } diff --git a/client/ui/pages_logic/WizardLogic.cpp b/client/ui/pages_logic/WizardLogic.cpp index 7936524da..5fe820f1f 100644 --- a/client/ui/pages_logic/WizardLogic.cpp +++ b/client/ui/pages_logic/WizardLogic.cpp @@ -55,9 +55,9 @@ void WizardLogic::onPushButtonVpnModeFinishClicked() auto containers = getInstallConfigsFromWizardPage(); uiLogic()->installServer(containers); if (checkBoxVpnModeChecked()) { - m_settings.setRouteMode(Settings::VpnOnlyForwardSites); + m_settings->setRouteMode(Settings::VpnOnlyForwardSites); } else { - m_settings.setRouteMode(Settings::VpnAllSites); + m_settings->setRouteMode(Settings::VpnAllSites); } } diff --git a/client/ui/pages_logic/protocols/CloakLogic.cpp b/client/ui/pages_logic/protocols/CloakLogic.cpp index 2e341383b..227f2e5cc 100644 --- a/client/ui/pages_logic/protocols/CloakLogic.cpp +++ b/client/ui/pages_logic/protocols/CloakLogic.cpp @@ -52,10 +52,10 @@ QJsonObject CloakLogic::getProtocolConfigFromPage(QJsonObject oldConfig) void CloakLogic::onPushButtonSaveClicked() { - QJsonObject protocolConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::Cloak); + QJsonObject protocolConfig = m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::Cloak); protocolConfig = getProtocolConfigFromPage(protocolConfig); - QJsonObject containerConfig = m_settings.containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); + QJsonObject containerConfig = m_settings->containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); QJsonObject newContainerConfig = containerConfig; newContainerConfig.insert(ProtocolProps::protoToString(Proto::Cloak), protocolConfig); @@ -89,14 +89,14 @@ void CloakLogic::onPushButtonSaveClicked() }; ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ - return ServerController::updateContainer(m_settings.serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); + return ServerController::updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); }, page_func, progressBar_reset, pushButton_save_func, label_info_func); if (!e) { - m_settings.setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); - m_settings.clearLastConnectionConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); + m_settings->setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); + m_settings->clearLastConnectionConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); } qDebug() << "Protocol saved with code:" << e << "for" << uiLogic()->selectedServerIndex << uiLogic()->selectedDockerContainer; diff --git a/client/ui/pages_logic/protocols/CloakLogic.h b/client/ui/pages_logic/protocols/CloakLogic.h index e110c4658..d88252c8f 100644 --- a/client/ui/pages_logic/protocols/CloakLogic.h +++ b/client/ui/pages_logic/protocols/CloakLogic.h @@ -32,7 +32,6 @@ class CloakLogic : public PageProtocolLogicBase QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override; private: - Settings m_settings; UiLogic *m_uiLogic; }; diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp index 98115f29b..e784dac9b 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp @@ -81,10 +81,10 @@ void OpenVpnLogic::updateProtocolPage(const QJsonObject &openvpnConfig, DockerCo void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked() { - QJsonObject protocolConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::OpenVpn); + QJsonObject protocolConfig = m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::OpenVpn); protocolConfig = getProtocolConfigFromPage(protocolConfig); - QJsonObject containerConfig = m_settings.containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); + QJsonObject containerConfig = m_settings->containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); QJsonObject newContainerConfig = containerConfig; newContainerConfig.insert(ProtocolProps::protoToString(Proto::OpenVpn), protocolConfig); @@ -118,14 +118,14 @@ void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked() }; ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ - return ServerController::updateContainer(m_settings.serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); + return ServerController::updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); }, page_proto_openvpn, progressBar_proto_openvpn_reset, pushButton_proto_openvpn_save, label_proto_openvpn_info); if (!e) { - m_settings.setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); - m_settings.clearLastConnectionConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); + m_settings->setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); + m_settings->clearLastConnectionConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); } qDebug() << "Protocol saved with code:" << e << "for" << uiLogic()->selectedServerIndex << uiLogic()->selectedDockerContainer; } diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.h b/client/ui/pages_logic/protocols/OpenVpnLogic.h index 1d5c7f780..45141050e 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.h +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.h @@ -44,7 +44,6 @@ class OpenVpnLogic : public PageProtocolLogicBase QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override; private: - Settings m_settings; UiLogic *m_uiLogic; }; diff --git a/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp b/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp index 8cf3949f1..329ca4dfe 100644 --- a/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp +++ b/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp @@ -82,7 +82,7 @@ void OtherProtocolsLogic::onPushButtonSftpMountDriveClicked() { QString mountPath; QString cmd; - QString host = m_settings.serverCredentials(uiLogic()->selectedServerIndex).hostName; + QString host = m_settings->serverCredentials(uiLogic()->selectedServerIndex).hostName; #ifdef Q_OS_WINDOWS diff --git a/client/ui/pages_logic/protocols/OtherProtocolsLogic.h b/client/ui/pages_logic/protocols/OtherProtocolsLogic.h index 8639ba543..508c29141 100644 --- a/client/ui/pages_logic/protocols/OtherProtocolsLogic.h +++ b/client/ui/pages_logic/protocols/OtherProtocolsLogic.h @@ -31,7 +31,6 @@ class OtherProtocolsLogic : public PageProtocolLogicBase //QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override; private: - Settings m_settings; UiLogic *m_uiLogic; #ifdef AMNEZIA_DESKTOP diff --git a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp index 9aa8d0f3b..9f00d6884 100644 --- a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp +++ b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp @@ -46,10 +46,10 @@ QJsonObject ShadowSocksLogic::getProtocolConfigFromPage(QJsonObject oldConfig) void ShadowSocksLogic::onPushButtonSaveClicked() { - QJsonObject protocolConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::ShadowSocks); + QJsonObject protocolConfig = m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::ShadowSocks); //protocolConfig = getShadowSocksConfigFromPage(protocolConfig); - QJsonObject containerConfig = m_settings.containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); + QJsonObject containerConfig = m_settings->containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); QJsonObject newContainerConfig = containerConfig; newContainerConfig.insert(ProtocolProps::protoToString(Proto::ShadowSocks), protocolConfig); UiLogic::PageFunc page_proto_shadowsocks; @@ -82,14 +82,14 @@ void ShadowSocksLogic::onPushButtonSaveClicked() }; ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ - return ServerController::updateContainer(m_settings.serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); + return ServerController::updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); }, page_proto_shadowsocks, progressBar_reset, pushButton_proto_shadowsocks_save, label_proto_shadowsocks_info); if (!e) { - m_settings.setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); - m_settings.clearLastConnectionConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); + m_settings->setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); + m_settings->clearLastConnectionConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); } qDebug() << "Protocol saved with code:" << e << "for" << uiLogic()->selectedServerIndex << uiLogic()->selectedDockerContainer; } diff --git a/client/ui/pages_logic/protocols/ShadowSocksLogic.h b/client/ui/pages_logic/protocols/ShadowSocksLogic.h index b7c2c9ee7..4e5668254 100644 --- a/client/ui/pages_logic/protocols/ShadowSocksLogic.h +++ b/client/ui/pages_logic/protocols/ShadowSocksLogic.h @@ -30,7 +30,6 @@ class ShadowSocksLogic : public PageProtocolLogicBase QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override; private: - Settings m_settings; UiLogic *m_uiLogic; }; diff --git a/client/ui/uilogic.cpp b/client/ui/uilogic.cpp index fe2d541d5..7cd4f7a00 100644 --- a/client/ui/uilogic.cpp +++ b/client/ui/uilogic.cpp @@ -74,13 +74,14 @@ using namespace amnezia; using namespace PageEnumNS; -UiLogic::UiLogic(QObject *parent) : +UiLogic::UiLogic(std::shared_ptr settings, QObject *parent) : QObject(parent), + m_settings(settings), m_dialogConnectErrorText{} { - m_containersModel = new ContainersModel(this); - m_protocolsModel = new ProtocolsModel(this); - m_vpnConnection = new VpnConnection(); + m_containersModel = new ContainersModel(settings, this); + m_protocolsModel = new ProtocolsModel(settings, this); + m_vpnConnection = new VpnConnection(settings); m_vpnConnection->moveToThread(&m_vpnConnectionThread); m_vpnConnectionThread.start(); @@ -158,15 +159,15 @@ void UiLogic::initalizeUiLogic() connect(m_notificationHandler, &NotificationHandler::connectRequested, vpnLogic(), &VpnLogic::onConnect); connect(m_notificationHandler, &NotificationHandler::disconnectRequested, vpnLogic(), &VpnLogic::onDisconnect); - if (m_settings.serversCount() > 0) { - if (m_settings.defaultServerIndex() < 0) m_settings.setDefaultServer(0); + if (m_settings->serversCount() > 0) { + if (m_settings->defaultServerIndex() < 0) m_settings->setDefaultServer(0); emit goToPage(Page::Vpn, true, false); } else { emit goToPage(Page::Start, true, false); } - selectedServerIndex = m_settings.defaultServerIndex(); + selectedServerIndex = m_settings->defaultServerIndex(); qInfo().noquote() << QString("Started %1 version %2").arg(APPLICATION_NAME).arg(APP_VERSION); qInfo().noquote() << QString("%1 (%2)").arg(QSysInfo::prettyProductName()).arg(QSysInfo::currentCpuArchitecture()); @@ -187,7 +188,7 @@ void UiLogic::setDialogConnectErrorText(const QString &dialogConnectErrorText) void UiLogic::showOnStartup() { - if (! m_settings.isStartMinimized()) { + if (! m_settings->isStartMinimized()) { emit show(); } else { @@ -235,30 +236,30 @@ void UiLogic::keyPressEvent(Qt::Key key) qApp->quit(); break; case Qt::Key_H: - selectedServerIndex = m_settings.defaultServerIndex(); - selectedDockerContainer = m_settings.defaultContainer(selectedServerIndex); + selectedServerIndex = m_settings->defaultServerIndex(); + selectedDockerContainer = m_settings->defaultContainer(selectedServerIndex); - //updateSharingPage(selectedServerIndex, m_settings.serverCredentials(selectedServerIndex), selectedDockerContainer); + //updateSharingPage(selectedServerIndex, m_settings->serverCredentials(selectedServerIndex), selectedDockerContainer); emit goToPage(Page::ShareConnection); break; #endif case Qt::Key_C: - qDebug().noquote() << "Def server" << m_settings.defaultServerIndex() << m_settings.defaultContainerName(m_settings.defaultServerIndex()); - //qDebug().noquote() << QJsonDocument(m_settings.containerConfig(m_settings.defaultServerIndex(), m_settings.defaultContainer(m_settings.defaultServerIndex()))).toJson(); - qDebug().noquote() << QJsonDocument(m_settings.defaultServer()).toJson(); + qDebug().noquote() << "Def server" << m_settings->defaultServerIndex() << m_settings->defaultContainerName(m_settings->defaultServerIndex()); + //qDebug().noquote() << QJsonDocument(m_settings->containerConfig(m_settings->defaultServerIndex(), m_settings->defaultContainer(m_settings->defaultServerIndex()))).toJson(); + qDebug().noquote() << QJsonDocument(m_settings->defaultServer()).toJson(); break; case Qt::Key_A: emit goToPage(Page::Start); break; case Qt::Key_S: - selectedServerIndex = m_settings.defaultServerIndex(); + selectedServerIndex = m_settings->defaultServerIndex(); emit goToPage(Page::ServerSettings); break; case Qt::Key_P: onGotoCurrentProtocolsPage(); break; case Qt::Key_T: - SshConfigurator::openSshTerminal(m_settings.serverCredentials(m_settings.defaultServerIndex())); + SshConfigurator::openSshTerminal(m_settings->serverCredentials(m_settings->defaultServerIndex())); break; case Qt::Key_Escape: case Qt::Key_Back: @@ -280,7 +281,7 @@ void UiLogic::keyPressEvent(Qt::Key key) void UiLogic::onCloseWindow() { - if (m_settings.serversCount() == 0) qApp->quit(); + if (m_settings->serversCount() == 0) qApp->quit(); else { hide(); } @@ -299,8 +300,8 @@ QString UiLogic::containerDesc(int container) void UiLogic::onGotoCurrentProtocolsPage() { - selectedServerIndex = m_settings.defaultServerIndex(); - selectedDockerContainer = m_settings.defaultContainer(selectedServerIndex); + selectedServerIndex = m_settings->defaultServerIndex(); + selectedDockerContainer = m_settings->defaultContainer(selectedServerIndex); emit goToPage(Page::ServerContainers); } @@ -385,7 +386,7 @@ void UiLogic::installServer(QMap &containers) server.insert(config_key::userName, installCredentials.userName); server.insert(config_key::password, installCredentials.password); server.insert(config_key::port, installCredentials.port); - server.insert(config_key::description, m_settings.nextAvailableServerName()); + server.insert(config_key::description, m_settings->nextAvailableServerName()); QJsonArray containerConfigs; for (const QJsonObject &cfg : containers) { @@ -394,8 +395,8 @@ void UiLogic::installServer(QMap &containers) server.insert(config_key::containers, containerConfigs); server.insert(config_key::defaultContainer, ContainerProps::containerToString(containers.firstKey())); - m_settings.addServer(server); - m_settings.setDefaultServer(m_settings.serversCount() - 1); + m_settings->addServer(server); + m_settings->setDefaultServer(m_settings->serversCount() - 1); onUpdateAllPages(); emit setStartPage(Page::Vpn); diff --git a/client/ui/uilogic.h b/client/ui/uilogic.h index 4e818bcc0..bbec24510 100644 --- a/client/ui/uilogic.h +++ b/client/ui/uilogic.h @@ -58,10 +58,12 @@ class UiLogic : public QObject Q_PROPERTY(QString dialogConnectErrorText READ getDialogConnectErrorText WRITE setDialogConnectErrorText NOTIFY dialogConnectErrorTextChanged) public: - explicit UiLogic(QObject *parent = nullptr); + explicit UiLogic(std::shared_ptr settings, QObject *parent = nullptr); ~UiLogic(); void showOnStartup(); + friend class PageLogicBase; + friend class AppSettingsLogic; friend class GeneralSettingsLogic; friend class NetworkSettingsLogic; @@ -212,7 +214,7 @@ private slots: VpnConnection* m_vpnConnection; QThread m_vpnConnectionThread; - Settings m_settings; + std::shared_ptr m_settings; NotificationHandler* m_notificationHandler; diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index d2461b073..baee8933a 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -29,9 +29,8 @@ #include "utils.h" #include "vpnconnection.h" -VpnConnection::VpnConnection(QObject* parent) : QObject(parent), - m_settings(this) - +VpnConnection::VpnConnection(std::shared_ptr settings, QObject* parent) : QObject(parent), + m_settings(settings) { } @@ -56,7 +55,7 @@ void VpnConnection::onConnectionStateChanged(VpnProtocol::VpnConnectionState sta IpcClient::Interface()->resetIpStack(); IpcClient::Interface()->flushDns(); - if (m_settings.routeMode() != Settings::VpnAllSites) { + if (m_settings->routeMode() != Settings::VpnAllSites) { IpcClient::Interface()->routeDeleteList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0"); //qDebug() << "VpnConnection::onConnectionStateChanged :: adding custom routes, count:" << forwardIps.size(); } @@ -67,17 +66,17 @@ void VpnConnection::onConnectionStateChanged(VpnProtocol::VpnConnectionState sta QStringList() << dns1 << dns2); - if (m_settings.routeMode() == Settings::VpnOnlyForwardSites) { + if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) { QTimer::singleShot(1000, m_vpnProtocol.data(), [this](){ - addSitesRoutes(m_vpnProtocol->vpnGateway(), m_settings.routeMode()); + addSitesRoutes(m_vpnProtocol->vpnGateway(), m_settings->routeMode()); }); } - else if (m_settings.routeMode() == Settings::VpnAllExceptSites) { + else if (m_settings->routeMode() == Settings::VpnAllExceptSites) { IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0/1"); IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "128.0.0.0/1"); IpcClient::Interface()->routeAddList(m_vpnProtocol->routeGateway(), QStringList() << remoteAddress()); - addSitesRoutes(m_vpnProtocol->routeGateway(), m_settings.routeMode()); + addSitesRoutes(m_vpnProtocol->routeGateway(), m_settings->routeMode()); } @@ -85,7 +84,7 @@ void VpnConnection::onConnectionStateChanged(VpnProtocol::VpnConnectionState sta else if (state == VpnProtocol::Error) { IpcClient::Interface()->flushDns(); - if (m_settings.routeMode() == Settings::VpnOnlyForwardSites) { + if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) { IpcClient::Interface()->clearSavedRoutes(); } } @@ -104,7 +103,7 @@ void VpnConnection::addSitesRoutes(const QString &gw, Settings::RouteMode mode) #ifdef AMNEZIA_DESKTOP QStringList ips; QStringList sites; - const QVariantMap &m = m_settings.vpnSites(mode); + const QVariantMap &m = m_settings->vpnSites(mode); for (auto i = m.constBegin(); i != m.constEnd(); ++i) { if (Utils::checkIpSubnetFormat(i.key())) { ips.append(i.key()); @@ -132,7 +131,7 @@ void VpnConnection::addSitesRoutes(const QString &gw, Settings::RouteMode mode) //qDebug() << "VpnConnection::addSitesRoutes updating site" << site << ip; if (!ips.contains(ip)) { IpcClient::Interface()->routeAddList(gw, QStringList() << ip); - m_settings.addVpnSite(mode, site, ip); + m_settings->addVpnSite(mode, site, ip); } flushDns(); break; @@ -153,10 +152,10 @@ void VpnConnection::addRoutes(const QStringList &ips) { #ifdef AMNEZIA_DESKTOP if (connectionState() == VpnProtocol::Connected && IpcClient::Interface()) { - if (m_settings.routeMode() == Settings::VpnOnlyForwardSites) { + if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) { IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), ips); } - else if (m_settings.routeMode() == Settings::VpnAllExceptSites) { + else if (m_settings->routeMode() == Settings::VpnAllExceptSites) { IpcClient::Interface()->routeAddList(m_vpnProtocol->routeGateway(), ips); } } @@ -167,10 +166,10 @@ void VpnConnection::deleteRoutes(const QStringList &ips) { #ifdef AMNEZIA_DESKTOP if (connectionState() == VpnProtocol::Connected && IpcClient::Interface()) { - if (m_settings.routeMode() == Settings::VpnOnlyForwardSites) { + if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) { IpcClient::Interface()->routeDeleteList(vpnProtocol()->vpnGateway(), ips); } - else if (m_settings.routeMode() == Settings::VpnAllExceptSites) { + else if (m_settings->routeMode() == Settings::VpnAllExceptSites) { IpcClient::Interface()->routeDeleteList(m_vpnProtocol->routeGateway(), ips); } } @@ -237,9 +236,9 @@ QString VpnConnection::createVpnConfigurationForProto(int serverIndex, if (serverIndex >= 0) { qDebug() << "VpnConnection::createVpnConfiguration: saving config for server #" << serverIndex << container << proto; - QJsonObject protoObject = m_settings.protocolConfig(serverIndex, container, proto); + QJsonObject protoObject = m_settings->protocolConfig(serverIndex, container, proto); protoObject.insert(config_key::last_config, configDataBeforeLocalProcessing); - m_settings.setProtocolConfig(serverIndex, container, proto, protoObject); + m_settings->setProtocolConfig(serverIndex, container, proto, protoObject); } } @@ -284,7 +283,7 @@ void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig) { qDebug() << QString("СonnectToVpn, Server index is %1, container is %2, route mode is") - .arg(serverIndex).arg(ContainerProps::containerToString(container)) << m_settings.routeMode(); + .arg(serverIndex).arg(ContainerProps::containerToString(container)) << m_settings->routeMode(); #if !defined (Q_OS_ANDROID) && !defined (Q_OS_IOS) if (!m_IpcClient) { diff --git a/client/vpnconnection.h b/client/vpnconnection.h index d0dc21359..86d096b6a 100644 --- a/client/vpnconnection.h +++ b/client/vpnconnection.h @@ -21,7 +21,7 @@ class VpnConnection : public QObject Q_OBJECT public: - explicit VpnConnection(QObject* parent = nullptr); + explicit VpnConnection(std::shared_ptr settings, QObject* parent = nullptr); ~VpnConnection() override; static QString bytesPerSecToText(quint64 bytes); @@ -73,7 +73,7 @@ protected slots: QSharedPointer m_vpnProtocol; private: - Settings m_settings; + std::shared_ptr m_settings; QJsonObject m_vpnConfiguration; QJsonObject m_routeMode; QString m_remoteAddress; From 3ce1ec708ddc0d4c9f4d5a80cf0122853f7468c9 Mon Sep 17 00:00:00 2001 From: pokamest Date: Thu, 25 Aug 2022 17:35:28 +0300 Subject: [PATCH 18/20] App refactoring finished --- client/amnezia_application.cpp | 15 ++--- client/amnezia_application.h | 3 + client/client.pro | 2 + client/configurators/cloak_configurator.cpp | 15 +++-- client/configurators/cloak_configurator.h | 13 ++-- client/configurators/configurator_base.cpp | 10 +++ client/configurators/configurator_base.h | 25 ++++++++ client/configurators/ikev2_configurator.cpp | 19 +++--- client/configurators/ikev2_configurator.h | 17 ++--- client/configurators/openvpn_configurator.cpp | 35 ++++++----- client/configurators/openvpn_configurator.h | 21 ++++--- .../shadowsocks_configurator.cpp | 13 +++- .../configurators/shadowsocks_configurator.h | 10 +-- client/configurators/ssh_configurator.cpp | 7 +++ client/configurators/ssh_configurator.h | 15 +++-- client/configurators/vpn_configurator.cpp | 38 ++++++----- client/configurators/vpn_configurator.h | 37 ++++++++--- .../configurators/wireguard_configurator.cpp | 45 ++++++------- client/configurators/wireguard_configurator.h | 20 +++--- client/core/servercontroller.cpp | 14 ++--- client/core/servercontroller.h | 63 ++++++++++--------- client/protocols/openvpnovercloakprotocol.cpp | 1 - client/protocols/shadowsocksvpnprotocol.cpp | 1 - .../ui/pages_logic/NetworkSettingsLogic.cpp | 1 + .../ui/pages_logic/NewServerProtocolsLogic.h | 1 + client/ui/pages_logic/PageLogicBase.cpp | 6 +- client/ui/pages_logic/PageLogicBase.h | 11 ++-- .../ServerConfiguringProgressLogic.h | 3 + .../ui/pages_logic/ServerContainersLogic.cpp | 6 +- client/ui/pages_logic/ServerContainersLogic.h | 1 + client/ui/pages_logic/ServerSettingsLogic.cpp | 6 +- .../ui/pages_logic/ShareConnectionLogic.cpp | 27 ++++---- client/ui/pages_logic/ShareConnectionLogic.h | 1 + client/ui/pages_logic/SitesLogic.h | 1 + client/ui/pages_logic/StartPageLogic.cpp | 5 +- client/ui/pages_logic/VpnLogic.cpp | 10 +-- client/ui/pages_logic/WizardLogic.h | 1 + .../ui/pages_logic/protocols/CloakLogic.cpp | 2 +- .../ui/pages_logic/protocols/OpenVpnLogic.cpp | 2 +- .../protocols/OtherProtocolsLogic.cpp | 1 - .../protocols/ShadowSocksLogic.cpp | 2 +- client/ui/property_helper.h | 4 +- client/ui/uilogic.cpp | 28 +++------ client/ui/uilogic.h | 21 +++---- client/vpnconnection.cpp | 18 +++--- client/vpnconnection.h | 10 ++- 46 files changed, 361 insertions(+), 246 deletions(-) create mode 100644 client/configurators/configurator_base.cpp create mode 100644 client/configurators/configurator_base.h diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp index 85762a078..a0776c309 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -7,12 +7,11 @@ #include "QZXing.h" +#include "core/servercontroller.h" #include "debug.h" #include "defines.h" - #include "platforms/ios/QRCodeReaderBase.h" -//#include "platforms/ios/MobileUtils.h" #include "ui/pages.h" @@ -49,14 +48,8 @@ AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecond { setQuitOnLastWindowClosed(false); m_settings = std::shared_ptr(new Settings); - -// QObject::connect(&app, &QCoreApplication::aboutToQuit, uiLogic, [&engine, uiLogic](){ -// QObject::disconnect(engine, 0,0,0); -// delete engine; - -// QObject::disconnect(uiLogic, 0,0,0); -// delete uiLogic; - // }); + m_serverController = std::shared_ptr(new ServerController(m_settings, this)); + m_configurator = std::shared_ptr(new VpnConfigurator(m_settings, m_serverController, this)); } AmneziaApplication::~AmneziaApplication() @@ -71,7 +64,7 @@ AmneziaApplication::~AmneziaApplication() void AmneziaApplication::init() { m_engine = new QQmlApplicationEngine; - m_uiLogic = new UiLogic(m_settings); + m_uiLogic = new UiLogic(m_settings, m_configurator, m_serverController); const QUrl url(QStringLiteral("qrc:/ui/qml/main.qml")); QObject::connect(m_engine, &QQmlApplicationEngine::objectCreated, diff --git a/client/amnezia_application.h b/client/amnezia_application.h index d7a768338..e0dfbc3a4 100644 --- a/client/amnezia_application.h +++ b/client/amnezia_application.h @@ -11,6 +11,7 @@ #include "settings.h" #include "ui/uilogic.h" +#include "configurators/vpn_configurator.h" #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) #define AMNEZIA_BASE_CLASS SingleApplication @@ -43,6 +44,8 @@ class AmneziaApplication : public AMNEZIA_BASE_CLASS QQmlApplicationEngine *m_engine; UiLogic *m_uiLogic; std::shared_ptr m_settings; + std::shared_ptr m_configurator; + std::shared_ptr m_serverController; QTranslator* m_translator; QCommandLineParser m_parser; diff --git a/client/client.pro b/client/client.pro index 5d9ab1ea7..996521d1d 100644 --- a/client/client.pro +++ b/client/client.pro @@ -26,6 +26,7 @@ HEADERS += \ ../ipc/ipc.h \ amnezia_application.h \ configurators/cloak_configurator.h \ + configurators/configurator_base.h \ configurators/ikev2_configurator.h \ configurators/shadowsocks_configurator.h \ configurators/ssh_configurator.h \ @@ -87,6 +88,7 @@ HEADERS += \ SOURCES += \ amnezia_application.cpp \ configurators/cloak_configurator.cpp \ + configurators/configurator_base.cpp \ configurators/ikev2_configurator.cpp \ configurators/shadowsocks_configurator.cpp \ configurators/ssh_configurator.cpp \ diff --git a/client/configurators/cloak_configurator.cpp b/client/configurators/cloak_configurator.cpp index 211ddc79f..50f554dc4 100644 --- a/client/configurators/cloak_configurator.cpp +++ b/client/configurators/cloak_configurator.cpp @@ -4,18 +4,25 @@ #include #include +#include "core/servercontroller.h" #include "containers/containers_defs.h" +CloakConfigurator::CloakConfigurator(std::shared_ptr settings, std::shared_ptr serverController, QObject *parent): + ConfiguratorBase(settings, serverController, parent) +{ + +} + QString CloakConfigurator::genCloakConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode) { ErrorCode e = ErrorCode::NoError; - QString cloakPublicKey = ServerController::getTextFileFromContainer(container, credentials, + QString cloakPublicKey = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::cloak::ckPublicKeyPath, &e); cloakPublicKey.replace("\n", ""); - QString cloakBypassUid = ServerController::getTextFileFromContainer(container, credentials, + QString cloakBypassUid = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::cloak::ckBypassUidKeyPath, &e); cloakBypassUid.replace("\n", ""); @@ -40,8 +47,8 @@ QString CloakConfigurator::genCloakConfig(const ServerCredentials &credentials, config.insert(config_key::remote, credentials.hostName); config.insert(config_key::port, "$CLOAK_SERVER_PORT"); - QString textCfg = ServerController::replaceVars(QJsonDocument(config).toJson(), - ServerController::genVarsForScript(credentials, container, containerConfig)); + QString textCfg = m_serverController->replaceVars(QJsonDocument(config).toJson(), + m_serverController->genVarsForScript(credentials, container, containerConfig)); // qDebug().noquote() << textCfg; return textCfg; diff --git a/client/configurators/cloak_configurator.h b/client/configurators/cloak_configurator.h index 562b99176..c61848052 100644 --- a/client/configurators/cloak_configurator.h +++ b/client/configurators/cloak_configurator.h @@ -3,15 +3,18 @@ #include -#include "core/defs.h" -#include "settings.h" -#include "core/servercontroller.h" +#include "configurator_base.h" -class CloakConfigurator +using namespace amnezia; + +class CloakConfigurator : ConfiguratorBase { + Q_OBJECT public: + CloakConfigurator(std::shared_ptr settings, + std::shared_ptr serverController, QObject *parent = nullptr); - static QString genCloakConfig(const ServerCredentials &credentials, DockerContainer container, + QString genCloakConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr); }; diff --git a/client/configurators/configurator_base.cpp b/client/configurators/configurator_base.cpp new file mode 100644 index 000000000..443774010 --- /dev/null +++ b/client/configurators/configurator_base.cpp @@ -0,0 +1,10 @@ +#include "configurator_base.h" + +ConfiguratorBase::ConfiguratorBase(std::shared_ptr settings, + std::shared_ptr serverController, QObject *parent) + : QObject{parent}, + m_settings(settings), + m_serverController(serverController) +{ + +} diff --git a/client/configurators/configurator_base.h b/client/configurators/configurator_base.h new file mode 100644 index 000000000..8c0614d9c --- /dev/null +++ b/client/configurators/configurator_base.h @@ -0,0 +1,25 @@ +#ifndef CONFIGURATORBASE_H +#define CONFIGURATORBASE_H + +#include + +class Settings; +class ServerController; + +#include "containers/containers_defs.h" +#include "core/defs.h" + +class ConfiguratorBase : public QObject +{ + Q_OBJECT +public: + explicit ConfiguratorBase(std::shared_ptr settings, + std::shared_ptr serverController, QObject *parent = nullptr); + +protected: + std::shared_ptr m_settings; + std::shared_ptr m_serverController; + +}; + +#endif // CONFIGURATORBASE_H diff --git a/client/configurators/ikev2_configurator.cpp b/client/configurators/ikev2_configurator.cpp index de9f0e827..db6b53a21 100644 --- a/client/configurators/ikev2_configurator.cpp +++ b/client/configurators/ikev2_configurator.cpp @@ -8,13 +8,18 @@ #include #include -#include "sftpdefs.h" - -#include "core/server_defs.h" #include "containers/containers_defs.h" +#include "core/server_defs.h" #include "core/scripts_registry.h" +#include "core/servercontroller.h" #include "utils.h" +Ikev2Configurator::Ikev2Configurator(std::shared_ptr settings, std::shared_ptr serverController, QObject *parent): + ConfiguratorBase(settings, serverController, parent) +{ + +} + Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const ServerCredentials &credentials, DockerContainer container, ErrorCode *errorCode) { @@ -35,16 +40,16 @@ Ikev2Configurator::ConnectionData Ikev2Configurator::prepareIkev2Config(const Se "--extKeyUsage serverAuth,clientAuth -8 \"%1\"") .arg(connData.clientId); - ErrorCode e = ServerController::runContainerScript(credentials, container, scriptCreateCert); + ErrorCode e = m_serverController->runContainerScript(credentials, container, scriptCreateCert); QString scriptExportCert = QString("pk12util -W \"%1\" -d sql:/etc/ipsec.d -n \"%2\" -o \"%3\"") .arg(connData.password) .arg(connData.clientId) .arg(certFileName); - e = ServerController::runContainerScript(credentials, container, scriptExportCert); + e = m_serverController->runContainerScript(credentials, container, scriptExportCert); - connData.clientCert = ServerController::getTextFileFromContainer(container, credentials, certFileName, &e); - connData.caCert = ServerController::getTextFileFromContainer(container, credentials, "/etc/ipsec.d/ca_cert_base64.p12", &e); + connData.clientCert = m_serverController->getTextFileFromContainer(container, credentials, certFileName, &e); + connData.caCert = m_serverController->getTextFileFromContainer(container, credentials, "/etc/ipsec.d/ca_cert_base64.p12", &e); qDebug() << "Ikev2Configurator::ConnectionData client cert size:" << connData.clientCert.size(); qDebug() << "Ikev2Configurator::ConnectionData ca cert size:" << connData.caCert.size(); diff --git a/client/configurators/ikev2_configurator.h b/client/configurators/ikev2_configurator.h index 9061a47c7..35c03b193 100644 --- a/client/configurators/ikev2_configurator.h +++ b/client/configurators/ikev2_configurator.h @@ -4,12 +4,15 @@ #include #include +#include "configurator_base.h" #include "core/defs.h" -#include "core/servercontroller.h" -class Ikev2Configurator +class Ikev2Configurator : ConfiguratorBase { + Q_OBJECT public: + Ikev2Configurator(std::shared_ptr settings, + std::shared_ptr serverController, QObject *parent = nullptr); struct ConnectionData { QByteArray clientCert; // p12 client cert @@ -19,14 +22,14 @@ class Ikev2Configurator QString host; // host ip }; - static QString genIkev2Config(const ServerCredentials &credentials, DockerContainer container, + QString genIkev2Config(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr); - static QString genIkev2Config(const ConnectionData &connData); - static QString genMobileConfig(const ConnectionData &connData); - static QString genStrongSwanConfig(const ConnectionData &connData); + QString genIkev2Config(const ConnectionData &connData); + QString genMobileConfig(const ConnectionData &connData); + QString genStrongSwanConfig(const ConnectionData &connData); - static ConnectionData prepareIkev2Config(const ServerCredentials &credentials, + ConnectionData prepareIkev2Config(const ServerCredentials &credentials, DockerContainer container, ErrorCode *errorCode = nullptr); }; diff --git a/client/configurators/openvpn_configurator.cpp b/client/configurators/openvpn_configurator.cpp index 3ebfefccf..a7719108a 100644 --- a/client/configurators/openvpn_configurator.cpp +++ b/client/configurators/openvpn_configurator.cpp @@ -6,16 +6,25 @@ #include #include #include +#include -#include "core/server_defs.h" #include "containers/containers_defs.h" +#include "core/server_defs.h" +#include "core/servercontroller.h" #include "core/scripts_registry.h" +#include "settings.h" #include "utils.h" #include #include #include +OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr settings, std::shared_ptr serverController, QObject *parent): + ConfiguratorBase(settings, serverController, parent) +{ + +} + OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container, ErrorCode *errorCode) { @@ -31,7 +40,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co arg(amnezia::protocols::openvpn::clientsDirPath). arg(connData.clientId); - ErrorCode e = ServerController::uploadTextFileToContainer(container, credentials, connData.request, reqFileName); + ErrorCode e = m_serverController->uploadTextFileToContainer(container, credentials, connData.request, reqFileName); if (e) { if (errorCode) *errorCode = e; return connData; @@ -43,8 +52,8 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co return connData; } - connData.caCert = ServerController::getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::caCertPath, &e); - connData.clientCert = ServerController::getTextFileFromContainer(container, credentials, + connData.caCert = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::caCertPath, &e); + connData.clientCert = m_serverController->getTextFileFromContainer(container, credentials, QString("%1/%2.crt").arg(amnezia::protocols::openvpn::clientCertPath).arg(connData.clientId), &e); if (e) { @@ -52,7 +61,7 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co return connData; } - connData.taKey = ServerController::getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::taKeyPath, &e); + connData.taKey = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::openvpn::taKeyPath, &e); if (connData.caCert.isEmpty() || connData.clientCert.isEmpty() || connData.taKey.isEmpty()) { if (errorCode) *errorCode = ErrorCode::RemoteProcessCrashError; @@ -61,17 +70,11 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co return connData; } -Settings &OpenVpnConfigurator::m_settings() -{ - static Settings s; - return s; -} - QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode) { - QString config = ServerController::replaceVars(amnezia::scriptData(ProtocolScriptType::openvpn_template, container), - ServerController::genVarsForScript(credentials, container, containerConfig)); + QString config = m_serverController->replaceVars(amnezia::scriptData(ProtocolScriptType::openvpn_template, container), + m_serverController->genVarsForScript(credentials, container, containerConfig)); ConnectionData connData = prepareOpenVpnConfig(credentials, container, errorCode); if (errorCode && *errorCode) { @@ -105,7 +108,7 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(QString jsonConfig) QJsonObject json = QJsonDocument::fromJson(jsonConfig.toUtf8()).object(); QString config = json[config_key::config].toString(); - if (m_settings().routeMode() != Settings::VpnAllSites) { + if (m_settings->routeMode() != Settings::VpnAllSites) { config.replace("redirect-gateway def1 bypass-dhcp", ""); } else { @@ -161,9 +164,9 @@ ErrorCode OpenVpnConfigurator::signCert(DockerContainer container, .arg(clientId); QStringList scriptList {script_import, script_sign}; - QString script = ServerController::replaceVars(scriptList.join("\n"), ServerController::genVarsForScript(credentials, container)); + QString script = m_serverController->replaceVars(scriptList.join("\n"), m_serverController->genVarsForScript(credentials, container)); - return ServerController::runScript(credentials, script); + return m_serverController->runScript(credentials, script); } OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest() diff --git a/client/configurators/openvpn_configurator.h b/client/configurators/openvpn_configurator.h index 99c4efa6c..252304997 100644 --- a/client/configurators/openvpn_configurator.h +++ b/client/configurators/openvpn_configurator.h @@ -4,13 +4,15 @@ #include #include +#include "configurator_base.h" #include "core/defs.h" -#include "settings.h" -#include "core/servercontroller.h" -class OpenVpnConfigurator +class OpenVpnConfigurator : ConfiguratorBase { + Q_OBJECT public: + OpenVpnConfigurator(std::shared_ptr settings, + std::shared_ptr serverController, QObject *parent = nullptr); struct ConnectionData { QString clientId; @@ -22,22 +24,21 @@ class OpenVpnConfigurator QString host; // host ip }; - static QString genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container, + QString genOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr); - static QString processConfigWithLocalSettings(QString jsonConfig); - static QString processConfigWithExportSettings(QString jsonConfig); + QString processConfigWithLocalSettings(QString jsonConfig); + QString processConfigWithExportSettings(QString jsonConfig); - static ErrorCode signCert(DockerContainer container, + ErrorCode signCert(DockerContainer container, const ServerCredentials &credentials, QString clientId); private: - static ConnectionData createCertRequest(); + ConnectionData createCertRequest(); - static ConnectionData prepareOpenVpnConfig(const ServerCredentials &credentials, + ConnectionData prepareOpenVpnConfig(const ServerCredentials &credentials, DockerContainer container, ErrorCode *errorCode = nullptr); - static Settings &m_settings(); }; #endif // OPENVPN_CONFIGURATOR_H diff --git a/client/configurators/shadowsocks_configurator.cpp b/client/configurators/shadowsocks_configurator.cpp index 6f63ba797..97503ac4a 100644 --- a/client/configurators/shadowsocks_configurator.cpp +++ b/client/configurators/shadowsocks_configurator.cpp @@ -5,13 +5,20 @@ #include #include "containers/containers_defs.h" +#include "core/servercontroller.h" + +ShadowSocksConfigurator::ShadowSocksConfigurator(std::shared_ptr settings, std::shared_ptr serverController, QObject *parent): + ConfiguratorBase(settings, serverController, parent) +{ + +} QString ShadowSocksConfigurator::genShadowSocksConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode) { ErrorCode e = ErrorCode::NoError; - QString ssKey = ServerController::getTextFileFromContainer(container, credentials, + QString ssKey = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::shadowsocks::ssKeyPath, &e); ssKey.replace("\n", ""); @@ -29,8 +36,8 @@ QString ShadowSocksConfigurator::genShadowSocksConfig(const ServerCredentials &c config.insert("method", "$SHADOWSOCKS_CIPHER"); - QString textCfg = ServerController::replaceVars(QJsonDocument(config).toJson(), - ServerController::genVarsForScript(credentials, container, containerConfig)); + QString textCfg = m_serverController->replaceVars(QJsonDocument(config).toJson(), + m_serverController->genVarsForScript(credentials, container, containerConfig)); //qDebug().noquote() << textCfg; return textCfg; diff --git a/client/configurators/shadowsocks_configurator.h b/client/configurators/shadowsocks_configurator.h index 4445b074f..be80f1690 100644 --- a/client/configurators/shadowsocks_configurator.h +++ b/client/configurators/shadowsocks_configurator.h @@ -3,15 +3,17 @@ #include +#include "configurator_base.h" #include "core/defs.h" -#include "settings.h" -#include "core/servercontroller.h" -class ShadowSocksConfigurator +class ShadowSocksConfigurator : ConfiguratorBase { + Q_OBJECT public: + ShadowSocksConfigurator(std::shared_ptr settings, + std::shared_ptr serverController, QObject *parent = nullptr); - static QString genShadowSocksConfig(const ServerCredentials &credentials, DockerContainer container, + QString genShadowSocksConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr); }; diff --git a/client/configurators/ssh_configurator.cpp b/client/configurators/ssh_configurator.cpp index fdece1d6e..ac867c708 100644 --- a/client/configurators/ssh_configurator.cpp +++ b/client/configurators/ssh_configurator.cpp @@ -14,8 +14,15 @@ #include "core/server_defs.h" #include "utils.h" +#include "sftpdefs.h" + using namespace QSsh; +SshConfigurator::SshConfigurator(std::shared_ptr settings, std::shared_ptr serverController, QObject *parent): + ConfiguratorBase(settings, serverController, parent) +{ + +} QString SshConfigurator::convertOpenSShKey(const QString &key) { diff --git a/client/configurators/ssh_configurator.h b/client/configurators/ssh_configurator.h index 71146a1ca..d7a177c38 100644 --- a/client/configurators/ssh_configurator.h +++ b/client/configurators/ssh_configurator.h @@ -4,16 +4,19 @@ #include #include +#include "configurator_base.h" #include "core/defs.h" -#include "settings.h" -#include "core/servercontroller.h" -class SshConfigurator +class SshConfigurator : ConfiguratorBase { + Q_OBJECT public: - static QProcessEnvironment prepareEnv(); - static QString convertOpenSShKey(const QString &key); - static void openSshTerminal(const ServerCredentials &credentials); + SshConfigurator(std::shared_ptr settings, + std::shared_ptr serverController, QObject *parent = nullptr); + + QProcessEnvironment prepareEnv(); + QString convertOpenSShKey(const QString &key); + void openSshTerminal(const ServerCredentials &credentials); }; diff --git a/client/configurators/vpn_configurator.cpp b/client/configurators/vpn_configurator.cpp index c2b128f09..42d3063ea 100644 --- a/client/configurators/vpn_configurator.cpp +++ b/client/configurators/vpn_configurator.cpp @@ -4,18 +4,26 @@ #include "shadowsocks_configurator.h" #include "wireguard_configurator.h" #include "ikev2_configurator.h" +#include "ssh_configurator.h" #include #include #include #include "containers/containers_defs.h" +#include "settings.h" #include "utils.h" -Settings &VpnConfigurator::m_settings() +VpnConfigurator::VpnConfigurator(std::shared_ptr settings, + std::shared_ptr serverController, QObject *parent): + ConfiguratorBase(settings, serverController, parent) { - static Settings s; - return s; + openVpnConfigurator = std::shared_ptr(new OpenVpnConfigurator(settings, serverController, this)); + shadowSocksConfigurator = std::shared_ptr(new ShadowSocksConfigurator(settings, serverController, this)); + cloakConfigurator = std::shared_ptr(new CloakConfigurator(settings, serverController, this)); + wireguardConfigurator = std::shared_ptr(new WireguardConfigurator(settings, serverController, this)); + ikev2Configurator = std::shared_ptr(new Ikev2Configurator(settings, serverController, this)); + sshConfigurator = std::shared_ptr(new SshConfigurator(settings, serverController, this)); } QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials, @@ -23,19 +31,19 @@ QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentia { switch (proto) { case Proto::OpenVpn: - return OpenVpnConfigurator::genOpenVpnConfig(credentials, container, containerConfig, errorCode); + return openVpnConfigurator->genOpenVpnConfig(credentials, container, containerConfig, errorCode); case Proto::ShadowSocks: - return ShadowSocksConfigurator::genShadowSocksConfig(credentials, container, containerConfig, errorCode); + return shadowSocksConfigurator->genShadowSocksConfig(credentials, container, containerConfig, errorCode); case Proto::Cloak: - return CloakConfigurator::genCloakConfig(credentials, container, containerConfig, errorCode); + return cloakConfigurator->genCloakConfig(credentials, container, containerConfig, errorCode); case Proto::WireGuard: - return WireguardConfigurator::genWireguardConfig(credentials, container, containerConfig, errorCode); + return wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig, errorCode); case Proto::Ikev2: - return Ikev2Configurator::genIkev2Config(credentials, container, containerConfig, errorCode); + return ikev2Configurator->genIkev2Config(credentials, container, containerConfig, errorCode); default: return ""; @@ -46,20 +54,20 @@ QPair VpnConfigurator::getDnsForConfig(int serverIndex) { QPair dns; - bool useAmneziaDns = m_settings().useAmneziaDns(); - const QJsonObject &server = m_settings().server(serverIndex); + bool useAmneziaDns = m_settings->useAmneziaDns(); + const QJsonObject &server = m_settings->server(serverIndex); dns.first = server.value(config_key::dns1).toString(); dns.second = server.value(config_key::dns2).toString(); if (dns.first.isEmpty() || !Utils::checkIPv4Format(dns.first)) { - if (useAmneziaDns && m_settings().containers(serverIndex).contains(DockerContainer::Dns)) { + if (useAmneziaDns && m_settings->containers(serverIndex).contains(DockerContainer::Dns)) { dns.first = protocols::dns::amneziaDnsIp; } - else dns.first = m_settings().primaryDns(); + else dns.first = m_settings->primaryDns(); } if (dns.second.isEmpty() || !Utils::checkIPv4Format(dns.second)) { - dns.second = m_settings().secondaryDns(); + dns.second = m_settings->secondaryDns(); } qDebug() << "VpnConfigurator::getDnsForConfig" << dns.first << dns.second; @@ -83,7 +91,7 @@ QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, Docker processConfigWithDnsSettings(serverIndex, container, proto, config); if (proto == Proto::OpenVpn) { - config = OpenVpnConfigurator::processConfigWithLocalSettings(config); + config = openVpnConfigurator->processConfigWithLocalSettings(config); } return config; } @@ -94,7 +102,7 @@ QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, Docke processConfigWithDnsSettings(serverIndex, container, proto, config); if (proto == Proto::OpenVpn) { - config = OpenVpnConfigurator::processConfigWithExportSettings(config); + config = openVpnConfigurator->processConfigWithExportSettings(config); } return config; } diff --git a/client/configurators/vpn_configurator.h b/client/configurators/vpn_configurator.h index 702fc9d40..47bdc1fd5 100644 --- a/client/configurators/vpn_configurator.h +++ b/client/configurators/vpn_configurator.h @@ -3,29 +3,46 @@ #include +#include "configurator_base.h" #include "core/defs.h" -#include "settings.h" -#include "core/servercontroller.h" + + +class OpenVpnConfigurator; +class ShadowSocksConfigurator; +class CloakConfigurator; +class WireguardConfigurator; +class Ikev2Configurator; +class SshConfigurator; // Retrieve connection settings from server -class VpnConfigurator +class VpnConfigurator : ConfiguratorBase { + Q_OBJECT public: + VpnConfigurator(std::shared_ptr settings, + std::shared_ptr serverController, QObject *parent = nullptr); - static QString genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container, + QString genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode = nullptr); - static QPair getDnsForConfig(int serverIndex); - static QString &processConfigWithDnsSettings(int serverIndex, DockerContainer container, Proto proto, QString &config); + QPair getDnsForConfig(int serverIndex); + QString &processConfigWithDnsSettings(int serverIndex, DockerContainer container, Proto proto, QString &config); - static QString &processConfigWithLocalSettings(int serverIndex, DockerContainer container, Proto proto, QString &config); - static QString &processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto, QString &config); + QString &processConfigWithLocalSettings(int serverIndex, DockerContainer container, Proto proto, QString &config); + QString &processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto, QString &config); // workaround for containers which is not support normal configaration - static void updateContainerConfigAfterInstallation(DockerContainer container, + void updateContainerConfigAfterInstallation(DockerContainer container, QJsonObject &containerConfig, const QString &stdOut); - static Settings &m_settings(); + std::shared_ptr m_serverController; + + std::shared_ptr openVpnConfigurator; + std::shared_ptr shadowSocksConfigurator; + std::shared_ptr cloakConfigurator; + std::shared_ptr wireguardConfigurator; + std::shared_ptr ikev2Configurator; + std::shared_ptr sshConfigurator; }; #endif // VPN_CONFIGURATOR_H diff --git a/client/configurators/wireguard_configurator.cpp b/client/configurators/wireguard_configurator.cpp index c7b29ef56..08e6c40a4 100644 --- a/client/configurators/wireguard_configurator.cpp +++ b/client/configurators/wireguard_configurator.cpp @@ -5,19 +5,28 @@ #include #include #include +#include + #include #include #include #include -#include "sftpdefs.h" -#include "core/server_defs.h" #include "containers/containers_defs.h" +#include "core/server_defs.h" #include "core/scripts_registry.h" +#include "core/servercontroller.h" +#include "settings.h" #include "utils.h" +WireguardConfigurator::WireguardConfigurator(std::shared_ptr settings, std::shared_ptr serverController, QObject *parent): + ConfiguratorBase(settings, serverController, parent) +{ + +} + WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys() { // TODO review @@ -71,7 +80,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon stdOut += data + "\n"; }; - ServerController::runContainerScript(credentials, container, script, cbReadStdOut); + m_serverController->runContainerScript(credentials, container, script, cbReadStdOut); stdOut.replace("AllowedIPs = ", ""); stdOut.replace("/32", ""); QStringList ips = stdOut.split("\n", Qt::SkipEmptyParts); @@ -104,14 +113,14 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon } // Get keys - connData.serverPubKey = ServerController::getTextFileFromContainer(container, credentials, amnezia::protocols::wireguard::serverPublicKeyPath, &e); + connData.serverPubKey = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::wireguard::serverPublicKeyPath, &e); connData.serverPubKey.replace("\n", ""); if (e) { if (errorCode) *errorCode = e; return connData; } - connData.pskKey = ServerController::getTextFileFromContainer(container, credentials, amnezia::protocols::wireguard::serverPskKeyPath, &e); + connData.pskKey = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::wireguard::serverPskKeyPath, &e); connData.pskKey.replace("\n", ""); if (e) { @@ -129,7 +138,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon arg(connData.pskKey). arg(connData.clientIP); - e = ServerController::uploadTextFileToContainer(container, credentials, configPart, + e = m_serverController->uploadTextFileToContainer(container, credentials, configPart, protocols::wireguard::serverConfigPath, QSsh::SftpOverwriteMode::SftpAppendToExisting); if (e) { @@ -137,24 +146,18 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon return connData; } - e = ServerController::runScript(credentials, - ServerController::replaceVars("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip /opt/amnezia/wireguard/wg0.conf)'", - ServerController::genVarsForScript(credentials, container))); + e = m_serverController->runScript(credentials, + m_serverController->replaceVars("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip /opt/amnezia/wireguard/wg0.conf)'", + m_serverController->genVarsForScript(credentials, container))); return connData; } -Settings &WireguardConfigurator::m_settings() -{ - static Settings s; - return s; -} - QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode) { - QString config = ServerController::replaceVars(amnezia::scriptData(ProtocolScriptType::wireguard_template, container), - ServerController::genVarsForScript(credentials, container, containerConfig)); + QString config = m_serverController->replaceVars(amnezia::scriptData(ProtocolScriptType::wireguard_template, container), + m_serverController->genVarsForScript(credentials, container, containerConfig)); ConnectionData connData = prepareWireguardConfig(credentials, container, containerConfig, errorCode); if (errorCode && *errorCode) { @@ -182,8 +185,8 @@ QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &crede QString WireguardConfigurator::processConfigWithLocalSettings(QString config) { // TODO replace DNS if it already set - config.replace("$PRIMARY_DNS", m_settings().primaryDns()); - config.replace("$SECONDARY_DNS", m_settings().secondaryDns()); + config.replace("$PRIMARY_DNS", m_settings->primaryDns()); + config.replace("$SECONDARY_DNS", m_settings->secondaryDns()); QJsonObject jConfig; jConfig[config_key::config] = config; @@ -193,8 +196,8 @@ QString WireguardConfigurator::processConfigWithLocalSettings(QString config) QString WireguardConfigurator::processConfigWithExportSettings(QString config) { - config.replace("$PRIMARY_DNS", m_settings().primaryDns()); - config.replace("$SECONDARY_DNS", m_settings().secondaryDns()); + config.replace("$PRIMARY_DNS", m_settings->primaryDns()); + config.replace("$SECONDARY_DNS", m_settings->secondaryDns()); return config; } diff --git a/client/configurators/wireguard_configurator.h b/client/configurators/wireguard_configurator.h index 635c8dce6..76790d74b 100644 --- a/client/configurators/wireguard_configurator.h +++ b/client/configurators/wireguard_configurator.h @@ -4,13 +4,15 @@ #include #include +#include "configurator_base.h" #include "core/defs.h" -#include "settings.h" -#include "core/servercontroller.h" -class WireguardConfigurator +class WireguardConfigurator : ConfiguratorBase { + Q_OBJECT public: + WireguardConfigurator(std::shared_ptr settings, + std::shared_ptr serverController, QObject *parent = nullptr); struct ConnectionData { QString clientPrivKey; // client private key @@ -21,20 +23,18 @@ class WireguardConfigurator QString host; // host ip }; - static QString genWireguardConfig(const ServerCredentials &credentials, DockerContainer container, + QString genWireguardConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr); - static QString processConfigWithLocalSettings(QString config); - static QString processConfigWithExportSettings(QString config); + QString processConfigWithLocalSettings(QString config); + QString processConfigWithExportSettings(QString config); private: - static ConnectionData prepareWireguardConfig(const ServerCredentials &credentials, + ConnectionData prepareWireguardConfig(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr); - static ConnectionData genClientKeys(); - - static Settings &m_settings(); + ConnectionData genClientKeys(); }; #endif // WIREGUARD_CONFIGURATOR_H diff --git a/client/core/servercontroller.cpp b/client/core/servercontroller.cpp index 638e12535..1ea36011d 100644 --- a/client/core/servercontroller.cpp +++ b/client/core/servercontroller.cpp @@ -18,18 +18,18 @@ #include "containers/containers_defs.h" #include "server_defs.h" +#include "settings.h" #include "scripts_registry.h" #include "utils.h" #include - using namespace QSsh; -Settings &ServerController::m_settings() +ServerController::ServerController(std::shared_ptr settings, QObject *parent) : + m_settings(settings) { - static Settings s; - return s; + } ErrorCode ServerController::runScript(const ServerCredentials &credentials, QString script, @@ -605,7 +605,7 @@ ErrorCode ServerController::configureContainerWorker(const ServerCredentials &cr cbReadStdOut, cbReadStdErr); - VpnConfigurator::updateContainerConfigAfterInstallation(container, config, stdOut); + m_configurator->updateContainerConfigAfterInstallation(container, config, stdOut); return e; } @@ -698,8 +698,8 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential vars.append({{"$IPSEC_VPN_C2C_TRAFFIC", "no"}}); - vars.append({{"$PRIMARY_SERVER_DNS", m_settings().primaryDns()}}); - vars.append({{"$SECONDARY_SERVER_DNS", m_settings().secondaryDns()}}); + vars.append({{"$PRIMARY_SERVER_DNS", m_settings->primaryDns()}}); + vars.append({{"$SECONDARY_SERVER_DNS", m_settings->secondaryDns()}}); // Sftp vars diff --git a/client/core/servercontroller.h b/client/core/servercontroller.h index 0f1e6cbf6..091eaa524 100644 --- a/client/core/servercontroller.h +++ b/client/core/servercontroller.h @@ -7,78 +7,83 @@ #include "sshremoteprocess.h" #include "debug.h" #include "defs.h" -#include "settings.h" #include "containers/containers_defs.h" #include "sftpdefs.h" +class Settings; +class VpnConfigurator; + using namespace amnezia; class ServerController : public QObject { Q_OBJECT public: + ServerController(std::shared_ptr settings, QObject *parent = nullptr); + typedef QList> Vars; - static ErrorCode fromSshConnectionErrorCode(QSsh::SshError error); + ErrorCode fromSshConnectionErrorCode(QSsh::SshError error); // QSsh exitCode and exitStatus are different things - static ErrorCode fromSshProcessExitStatus(int exitStatus); + ErrorCode fromSshProcessExitStatus(int exitStatus); - static QSsh::SshConnectionParameters sshParams(const ServerCredentials &credentials); - static void disconnectFromHost(const ServerCredentials &credentials); + QSsh::SshConnectionParameters sshParams(const ServerCredentials &credentials); + void disconnectFromHost(const ServerCredentials &credentials); - static ErrorCode removeAllContainers(const ServerCredentials &credentials); - static ErrorCode removeContainer(const ServerCredentials &credentials, DockerContainer container); - static ErrorCode setupContainer(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config); - static ErrorCode updateContainer(const ServerCredentials &credentials, DockerContainer container, + ErrorCode removeAllContainers(const ServerCredentials &credentials); + ErrorCode removeContainer(const ServerCredentials &credentials, DockerContainer container); + ErrorCode setupContainer(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config); + ErrorCode updateContainer(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &oldConfig, QJsonObject &newConfig); // create initial config - generate passwords, etc - static QJsonObject createContainerInitialConfig(DockerContainer container, int port, TransportProto tp); + QJsonObject createContainerInitialConfig(DockerContainer container, int port, TransportProto tp); - static bool isReinstallContainerRequred(DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig); + bool isReinstallContainerRequred(DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig); - static ErrorCode checkOpenVpnServer(DockerContainer container, const ServerCredentials &credentials); + ErrorCode checkOpenVpnServer(DockerContainer container, const ServerCredentials &credentials); - static ErrorCode uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, + ErrorCode uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, const QString &remotePath, QSsh::SftpOverwriteMode overwriteMode = QSsh::SftpOverwriteMode::SftpOverwriteExisting); - static ErrorCode uploadTextFileToContainer(DockerContainer container, + ErrorCode uploadTextFileToContainer(DockerContainer container, const ServerCredentials &credentials, const QString &file, const QString &path, QSsh::SftpOverwriteMode overwriteMode = QSsh::SftpOverwriteMode::SftpOverwriteExisting); - static QByteArray getTextFileFromContainer(DockerContainer container, + QByteArray getTextFileFromContainer(DockerContainer container, const ServerCredentials &credentials, const QString &path, ErrorCode *errorCode = nullptr); - static ErrorCode setupServerFirewall(const ServerCredentials &credentials); + ErrorCode setupServerFirewall(const ServerCredentials &credentials); - static QString replaceVars(const QString &script, const Vars &vars); + QString replaceVars(const QString &script, const Vars &vars); - static ErrorCode runScript(const ServerCredentials &credentials, QString script, + ErrorCode runScript(const ServerCredentials &credentials, QString script, const std::function)> &cbReadStdOut = nullptr, const std::function)> &cbReadStdErr = nullptr); - static ErrorCode runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script, + ErrorCode runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script, const std::function)> &cbReadStdOut = nullptr, const std::function)> &cbReadStdErr = nullptr); - static Vars genVarsForScript(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None, const QJsonObject &config = QJsonObject()); + Vars genVarsForScript(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None, const QJsonObject &config = QJsonObject()); - static QString checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode = nullptr); - static QSsh::SshConnection *connectToHost(const QSsh::SshConnectionParameters &sshParams); + QString checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode = nullptr); + QSsh::SshConnection *connectToHost(const QSsh::SshConnectionParameters &sshParams); private: - static ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container); - static ErrorCode prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject()); - static ErrorCode buildContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject()); - static ErrorCode runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config); - static ErrorCode configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config); - static ErrorCode startupContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject()); + ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container); + ErrorCode prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject()); + ErrorCode buildContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject()); + ErrorCode runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config); + ErrorCode configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config); + ErrorCode startupContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject()); - static Settings &m_settings(); + std::shared_ptr m_settings; + std::shared_ptr m_configurator; }; #endif // SERVERCONTROLLER_H diff --git a/client/protocols/openvpnovercloakprotocol.cpp b/client/protocols/openvpnovercloakprotocol.cpp index 2e9d77e85..5695b3dcf 100644 --- a/client/protocols/openvpnovercloakprotocol.cpp +++ b/client/protocols/openvpnovercloakprotocol.cpp @@ -1,5 +1,4 @@ #include "openvpnovercloakprotocol.h" -#include "core/servercontroller.h" #include "utils.h" #include "containers/containers_defs.h" diff --git a/client/protocols/shadowsocksvpnprotocol.cpp b/client/protocols/shadowsocksvpnprotocol.cpp index bc4947776..3de0bfe8e 100644 --- a/client/protocols/shadowsocksvpnprotocol.cpp +++ b/client/protocols/shadowsocksvpnprotocol.cpp @@ -1,5 +1,4 @@ #include "shadowsocksvpnprotocol.h" -#include "core/servercontroller.h" #include "debug.h" #include "utils.h" diff --git a/client/ui/pages_logic/NetworkSettingsLogic.cpp b/client/ui/pages_logic/NetworkSettingsLogic.cpp index f7e77378e..4038d089d 100644 --- a/client/ui/pages_logic/NetworkSettingsLogic.cpp +++ b/client/ui/pages_logic/NetworkSettingsLogic.cpp @@ -1,6 +1,7 @@ #include "NetworkSettingsLogic.h" #include "defines.h" +#include "settings.h" #include "utils.h" NetworkSettingsLogic::NetworkSettingsLogic(UiLogic *logic, QObject *parent): diff --git a/client/ui/pages_logic/NewServerProtocolsLogic.h b/client/ui/pages_logic/NewServerProtocolsLogic.h index a06e65907..abf3d1029 100644 --- a/client/ui/pages_logic/NewServerProtocolsLogic.h +++ b/client/ui/pages_logic/NewServerProtocolsLogic.h @@ -2,6 +2,7 @@ #define NEW_SERVER_PROTOCOLS_LOGIC_H #include "PageLogicBase.h" +#include "containers/containers_defs.h" class UiLogic; diff --git a/client/ui/pages_logic/PageLogicBase.cpp b/client/ui/pages_logic/PageLogicBase.cpp index 78fd15d78..9274ef49b 100644 --- a/client/ui/pages_logic/PageLogicBase.cpp +++ b/client/ui/pages_logic/PageLogicBase.cpp @@ -1,6 +1,8 @@ #include "PageLogicBase.h" -#include "ui/uilogic.h" +#include "ui/uilogic.h" +#include "settings.h" +#include "configurators/vpn_configurator.h" PageLogicBase::PageLogicBase(UiLogic *logic, QObject *parent): QObject(parent), @@ -8,6 +10,8 @@ PageLogicBase::PageLogicBase(UiLogic *logic, QObject *parent): m_uiLogic(logic) { m_settings = logic->m_settings; + m_configurator = logic->m_configurator; + m_serverController = logic->m_serverController; } diff --git a/client/ui/pages_logic/PageLogicBase.h b/client/ui/pages_logic/PageLogicBase.h index 22df01349..887b0ec7c 100644 --- a/client/ui/pages_logic/PageLogicBase.h +++ b/client/ui/pages_logic/PageLogicBase.h @@ -1,14 +1,15 @@ #ifndef PAGE_LOGIC_BASE_H #define PAGE_LOGIC_BASE_H -#include "settings.h" #include "../pages.h" #include "../property_helper.h" -using namespace amnezia; using namespace PageEnumNS; class UiLogic; +class Settings; +class VpnConfigurator; +class ServerController; class PageLogicBase : public QObject { @@ -22,10 +23,12 @@ class PageLogicBase : public QObject Q_INVOKABLE virtual void onUpdatePage() {} protected: + UiLogic *m_uiLogic; UiLogic *uiLogic() const { return m_uiLogic; } - std::shared_ptr m_settings; - UiLogic *m_uiLogic; + std::shared_ptr m_settings; + std::shared_ptr m_configurator; + std::shared_ptr m_serverController; signals: void updatePage(); diff --git a/client/ui/pages_logic/ServerConfiguringProgressLogic.h b/client/ui/pages_logic/ServerConfiguringProgressLogic.h index 9620d4c36..3ca948784 100644 --- a/client/ui/pages_logic/ServerConfiguringProgressLogic.h +++ b/client/ui/pages_logic/ServerConfiguringProgressLogic.h @@ -3,6 +3,9 @@ #include #include "PageLogicBase.h" +#include "core/defs.h" + +using namespace amnezia; class UiLogic; diff --git a/client/ui/pages_logic/ServerContainersLogic.cpp b/client/ui/pages_logic/ServerContainersLogic.cpp index 8822ed922..6e021a45c 100644 --- a/client/ui/pages_logic/ServerContainersLogic.cpp +++ b/client/ui/pages_logic/ServerContainersLogic.cpp @@ -67,7 +67,7 @@ void ServerContainersLogic::onPushButtonShareClicked(DockerContainer c) void ServerContainersLogic::onPushButtonRemoveClicked(DockerContainer container) { //buttonSetEnabledFunc(false); - ErrorCode e = ServerController::removeContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), container); + ErrorCode e = m_serverController->removeContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), container); m_settings->removeContainerConfig(uiLogic()->selectedServerIndex, container); //buttonSetEnabledFunc(true); @@ -81,13 +81,13 @@ void ServerContainersLogic::onPushButtonRemoveClicked(DockerContainer container) void ServerContainersLogic::onPushButtonContinueClicked(DockerContainer c, int port, TransportProto tp) { - QJsonObject config = ServerController::createContainerInitialConfig(c, port, tp); + QJsonObject config = m_serverController->createContainerInitialConfig(c, port, tp); emit uiLogic()->goToPage(Page::ServerConfiguringProgress); qApp->processEvents(); ErrorCode e = uiLogic()->serverConfiguringProgressLogic()->doInstallAction([this, c, &config](){ - return ServerController::setupContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), c, config); + return m_serverController->setupContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), c, config); }); if (!e) { diff --git a/client/ui/pages_logic/ServerContainersLogic.h b/client/ui/pages_logic/ServerContainersLogic.h index a49882fa9..3f2a26cd0 100644 --- a/client/ui/pages_logic/ServerContainersLogic.h +++ b/client/ui/pages_logic/ServerContainersLogic.h @@ -2,6 +2,7 @@ #define SERVER_CONTAINERS_LOGIC_H #include "PageLogicBase.h" +#include "containers/containers_defs.h" class UiLogic; diff --git a/client/ui/pages_logic/ServerSettingsLogic.cpp b/client/ui/pages_logic/ServerSettingsLogic.cpp index e23660fae..ddf9504e8 100644 --- a/client/ui/pages_logic/ServerSettingsLogic.cpp +++ b/client/ui/pages_logic/ServerSettingsLogic.cpp @@ -52,10 +52,10 @@ void ServerSettingsLogic::onPushButtonClearServer() uiLogic()->vpnLogic()->onDisconnect(); } - ErrorCode e = ServerController::removeAllContainers(m_settings->serverCredentials(uiLogic()->selectedServerIndex)); - ServerController::disconnectFromHost(m_settings->serverCredentials(uiLogic()->selectedServerIndex)); + ErrorCode e = m_serverController->removeAllContainers(m_settings->serverCredentials(uiLogic()->selectedServerIndex)); + m_serverController->disconnectFromHost(m_settings->serverCredentials(uiLogic()->selectedServerIndex)); if (e) { - uiLogic()->setDialogConnectErrorText( + uiLogic()->set_dialogConnectErrorText( tr("Error occurred while configuring server.") + "\n" + errorString(e) + "\n" + tr("See logs for details.")); diff --git a/client/ui/pages_logic/ShareConnectionLogic.cpp b/client/ui/pages_logic/ShareConnectionLogic.cpp index 1b042a295..2e4404984 100644 --- a/client/ui/pages_logic/ShareConnectionLogic.cpp +++ b/client/ui/pages_logic/ShareConnectionLogic.cpp @@ -21,6 +21,7 @@ #include "defines.h" #include "core/defs.h" #include "core/errorstrings.h" +#include "core/servercontroller.h" #include #include "../uilogic.h" @@ -85,7 +86,7 @@ void ShareConnectionLogic::onPushButtonShareAmneziaGenerateClicked() for (Proto p: ContainerProps::protocolsForContainer(container)) { QJsonObject protoConfig = m_settings->protocolConfig(serverIndex, container, p); - QString cfg = VpnConfigurator::genVpnProtocolConfig(credentials, container, containerConfig, p, &e); + QString cfg = m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, p, &e); if (e) { cfg = "Error generating config"; break; @@ -103,7 +104,7 @@ void ShareConnectionLogic::onPushButtonShareAmneziaGenerateClicked() serverConfig.insert(config_key::containers, QJsonArray {containerConfig}); serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(container)); - auto dns = VpnConfigurator::getDnsForConfig(serverIndex); + auto dns = m_configurator->getDnsForConfig(serverIndex); serverConfig.insert(config_key::dns1, dns.first); serverConfig.insert(config_key::dns2, dns.second); @@ -134,8 +135,8 @@ void ShareConnectionLogic::onPushButtonShareOpenVpnGenerateClicked() const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container); ErrorCode e = ErrorCode::NoError; - QString cfg = OpenVpnConfigurator::genOpenVpnConfig(credentials, container, containerConfig, &e); - cfg = VpnConfigurator::processConfigWithExportSettings(serverIndex, container, Proto::OpenVpn, cfg); + QString cfg = m_configurator->openVpnConfigurator->genOpenVpnConfig(credentials, container, containerConfig, &e); + cfg = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::OpenVpn, cfg); set_textEditShareOpenVpnCodeText(QJsonDocument::fromJson(cfg.toUtf8()).object()[config_key::config].toString()); } @@ -153,7 +154,7 @@ void ShareConnectionLogic::onPushButtonShareShadowSocksGenerateClicked() const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container); ErrorCode e = ErrorCode::NoError; - cfg = ShadowSocksConfigurator::genShadowSocksConfig(credentials, container, containerConfig, &e); + cfg = m_configurator->shadowSocksConfigurator->genShadowSocksConfig(credentials, container, containerConfig, &e); } QJsonObject ssConfig = QJsonDocument::fromJson(cfg.toUtf8()).object(); @@ -195,7 +196,7 @@ void ShareConnectionLogic::onPushButtonShareCloakGenerateClicked() const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container); ErrorCode e = ErrorCode::NoError; - cfg = CloakConfigurator::genCloakConfig(credentials, container, containerConfig, &e); + cfg = m_configurator->cloakConfigurator->genCloakConfig(credentials, container, containerConfig, &e); } QJsonObject cloakConfig = QJsonDocument::fromJson(cfg.toUtf8()).object(); @@ -214,14 +215,14 @@ void ShareConnectionLogic::onPushButtonShareWireGuardGenerateClicked() const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container); ErrorCode e = ErrorCode::NoError; - QString cfg = WireguardConfigurator::genWireguardConfig(credentials, container, containerConfig, &e); + QString cfg = m_configurator->wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig, &e); if (e) { QMessageBox::warning(nullptr, APPLICATION_NAME, tr("Error occurred while configuring server.") + "\n" + errorString(e)); return; } - cfg = VpnConfigurator::processConfigWithExportSettings(serverIndex, container, Proto::WireGuard, cfg); + cfg = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::WireGuard, cfg); cfg = QJsonDocument::fromJson(cfg.toUtf8()).object()[config_key::config].toString(); set_textEditShareWireGuardCodeText(cfg); @@ -239,18 +240,18 @@ void ShareConnectionLogic::onPushButtonShareIkev2GenerateClicked() //const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container); - Ikev2Configurator::ConnectionData connData = Ikev2Configurator::prepareIkev2Config(credentials, container); + Ikev2Configurator::ConnectionData connData = m_configurator->ikev2Configurator->prepareIkev2Config(credentials, container); - QString cfg = Ikev2Configurator::genIkev2Config(connData); - cfg = VpnConfigurator::processConfigWithExportSettings(serverIndex, container, Proto::Ikev2, cfg); + QString cfg = m_configurator->ikev2Configurator->genIkev2Config(connData); + cfg = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::Ikev2, cfg); cfg = QJsonDocument::fromJson(cfg.toUtf8()).object()[config_key::cert].toString(); set_textEditShareIkev2CertText(cfg); - QString mobileCfg = Ikev2Configurator::genMobileConfig(connData); + QString mobileCfg = m_configurator->ikev2Configurator->genMobileConfig(connData); set_textEditShareIkev2MobileConfigText(mobileCfg); - QString strongSwanCfg = Ikev2Configurator::genStrongSwanConfig(connData); + QString strongSwanCfg = m_configurator->ikev2Configurator->genStrongSwanConfig(connData); set_textEditShareIkev2StrongSwanConfigText(strongSwanCfg); } diff --git a/client/ui/pages_logic/ShareConnectionLogic.h b/client/ui/pages_logic/ShareConnectionLogic.h index c3c2ad6df..a167b43e2 100644 --- a/client/ui/pages_logic/ShareConnectionLogic.h +++ b/client/ui/pages_logic/ShareConnectionLogic.h @@ -2,6 +2,7 @@ #define SHARE_CONNECTION_LOGIC_H #include "PageLogicBase.h" +#include "containers/containers_defs.h" class UiLogic; diff --git a/client/ui/pages_logic/SitesLogic.h b/client/ui/pages_logic/SitesLogic.h index 2afb3805c..35bf1f90c 100644 --- a/client/ui/pages_logic/SitesLogic.h +++ b/client/ui/pages_logic/SitesLogic.h @@ -2,6 +2,7 @@ #define SITES_LOGIC_H #include "PageLogicBase.h" +#include "settings.h" class UiLogic; class SitesModel; diff --git a/client/ui/pages_logic/StartPageLogic.cpp b/client/ui/pages_logic/StartPageLogic.cpp index 2dd8ef626..b7b5907e0 100644 --- a/client/ui/pages_logic/StartPageLogic.cpp +++ b/client/ui/pages_logic/StartPageLogic.cpp @@ -1,6 +1,7 @@ #include "StartPageLogic.h" #include "core/errorstrings.h" #include "configurators/ssh_configurator.h" +#include "configurators/vpn_configurator.h" #include "../uilogic.h" #include "utils.h" @@ -83,7 +84,7 @@ void StartPageLogic::onPushButtonConnect() } if (key.contains("OPENSSH") && key.contains("BEGIN") && key.contains("PRIVATE KEY")) { - key = SshConfigurator::convertOpenSShKey(key); + key = m_configurator->sshConfigurator->convertOpenSShKey(key); } serverCredentials.password = key; @@ -97,7 +98,7 @@ void StartPageLogic::onPushButtonConnect() ErrorCode e = ErrorCode::NoError; #ifdef Q_DEBUG - //QString output = ServerController::checkSshConnection(serverCredentials, &e); + //QString output = m_serverController->checkSshConnection(serverCredentials, &e); #else QString output; #endif diff --git a/client/ui/pages_logic/VpnLogic.cpp b/client/ui/pages_logic/VpnLogic.cpp index 1bfd230ca..44a37a5ce 100644 --- a/client/ui/pages_logic/VpnLogic.cpp +++ b/client/ui/pages_logic/VpnLogic.cpp @@ -69,7 +69,7 @@ void VpnLogic::onUpdatePage() QString selectedContainerName = ContainerProps::containerHumanNames().value(selectedContainer); set_labelCurrentService(selectedContainerName); - auto dns = VpnConfigurator::getDnsForConfig(m_settings->defaultServerIndex()); + auto dns = m_configurator->getDnsForConfig(m_settings->defaultServerIndex()); set_amneziaDnsEnabled(dns.first == protocols::dns::amneziaDnsIp); if (dns.first == protocols::dns::amneziaDnsIp) { set_labelCurrentDns("On your server"); @@ -233,14 +233,6 @@ void VpnLogic::onConnectWorker(int serverIndex, const ServerCredentials &credent qApp->processEvents(); emit connectToVpn(serverIndex, credentials, container, containerConfig); - -// if (errorCode) { -// //ui->pushButton_connect->setChecked(false); -// uiLogic()->setDialogConnectErrorText(errorString(errorCode)); -// emit uiLogic()->showConnectErrorDialog(); -// return; -// } - } void VpnLogic::onDisconnect() diff --git a/client/ui/pages_logic/WizardLogic.h b/client/ui/pages_logic/WizardLogic.h index cfba5d2d6..3827c86e2 100644 --- a/client/ui/pages_logic/WizardLogic.h +++ b/client/ui/pages_logic/WizardLogic.h @@ -2,6 +2,7 @@ #define WIZARD_LOGIC_H #include "PageLogicBase.h" +#include "containers/containers_defs.h" class UiLogic; diff --git a/client/ui/pages_logic/protocols/CloakLogic.cpp b/client/ui/pages_logic/protocols/CloakLogic.cpp index 227f2e5cc..590199901 100644 --- a/client/ui/pages_logic/protocols/CloakLogic.cpp +++ b/client/ui/pages_logic/protocols/CloakLogic.cpp @@ -89,7 +89,7 @@ void CloakLogic::onPushButtonSaveClicked() }; ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ - return ServerController::updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); + return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); }, page_func, progressBar_reset, pushButton_save_func, label_info_func); diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp index e784dac9b..3b672747e 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp @@ -118,7 +118,7 @@ void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked() }; ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ - return ServerController::updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); + return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); }, page_proto_openvpn, progressBar_proto_openvpn_reset, pushButton_proto_openvpn_save, label_proto_openvpn_info); diff --git a/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp b/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp index 329ca4dfe..50b17a464 100644 --- a/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp +++ b/client/ui/pages_logic/protocols/OtherProtocolsLogic.cpp @@ -5,7 +5,6 @@ #include #include "OtherProtocolsLogic.h" -#include "core/servercontroller.h" #include #include "../../uilogic.h" #include "utils.h" diff --git a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp index 9f00d6884..e26efac1e 100644 --- a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp +++ b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp @@ -82,7 +82,7 @@ void ShadowSocksLogic::onPushButtonSaveClicked() }; ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ - return ServerController::updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); + return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); }, page_proto_shadowsocks, progressBar_reset, pushButton_proto_shadowsocks_save, label_proto_shadowsocks_info); diff --git a/client/ui/property_helper.h b/client/ui/property_helper.h index 3d254c717..927105b3b 100644 --- a/client/ui/property_helper.h +++ b/client/ui/property_helper.h @@ -14,7 +14,7 @@ } \ Q_SIGNAL void NAME ## Changed(TYPE value);\ private: \ - TYPE m_ ## NAME; + TYPE m_ ## NAME{}; #define READONLY_PROPERTY(TYPE, NAME) \ Q_PROPERTY(TYPE NAME READ NAME CONSTANT ) \ @@ -22,6 +22,6 @@ TYPE NAME() const { return m_ ## NAME ; } \ private: \ void NAME(TYPE value) {m_ ## NAME = value; } \ - TYPE m_ ## NAME; + TYPE m_ ## NAME{}; #endif // PROPERTY_HELPER_H diff --git a/client/ui/uilogic.cpp b/client/ui/uilogic.cpp index 7cd4f7a00..555c6bdc1 100644 --- a/client/ui/uilogic.cpp +++ b/client/ui/uilogic.cpp @@ -74,14 +74,17 @@ using namespace amnezia; using namespace PageEnumNS; -UiLogic::UiLogic(std::shared_ptr settings, QObject *parent) : +UiLogic::UiLogic(std::shared_ptr settings, std::shared_ptr configurator, + std::shared_ptr serverController, + QObject *parent) : QObject(parent), m_settings(settings), - m_dialogConnectErrorText{} + m_configurator(configurator), + m_serverController(serverController) { m_containersModel = new ContainersModel(settings, this); m_protocolsModel = new ProtocolsModel(settings, this); - m_vpnConnection = new VpnConnection(settings); + m_vpnConnection = new VpnConnection(settings, configurator, serverController); m_vpnConnection->moveToThread(&m_vpnConnectionThread); m_vpnConnectionThread.start(); @@ -173,19 +176,6 @@ void UiLogic::initalizeUiLogic() qInfo().noquote() << QString("%1 (%2)").arg(QSysInfo::prettyProductName()).arg(QSysInfo::currentCpuArchitecture()); } -QString UiLogic::getDialogConnectErrorText() const -{ - return m_dialogConnectErrorText; -} - -void UiLogic::setDialogConnectErrorText(const QString &dialogConnectErrorText) -{ - if (m_dialogConnectErrorText != dialogConnectErrorText) { - m_dialogConnectErrorText = dialogConnectErrorText; - emit dialogConnectErrorTextChanged(); - } -} - void UiLogic::showOnStartup() { if (! m_settings->isStartMinimized()) { @@ -259,7 +249,7 @@ void UiLogic::keyPressEvent(Qt::Key key) onGotoCurrentProtocolsPage(); break; case Qt::Key_T: - SshConfigurator::openSshTerminal(m_settings->serverCredentials(m_settings->defaultServerIndex())); + m_configurator->sshConfigurator->openSshTerminal(m_settings->serverCredentials(m_settings->defaultServerIndex())); break; case Qt::Key_Escape: case Qt::Key_Back: @@ -443,9 +433,9 @@ bool UiLogic::installContainers(ServerCredentials credentials, progress.setTextVisibleFunc(true); progress.setTextFunc(QString("Installing %1 %2 %3").arg(cnt+1).arg(tr("of")).arg(containers.size())); - ErrorCode e = ServerController::setupContainer(credentials, i.key(), i.value()); + ErrorCode e = m_serverController->setupContainer(credentials, i.key(), i.value()); qDebug() << "Setup server finished with code" << e; - ServerController::disconnectFromHost(credentials); + m_serverController->disconnectFromHost(credentials); if (e) { if (page.setEnabledFunc) { diff --git a/client/ui/uilogic.h b/client/ui/uilogic.h index bbec24510..ecf244212 100644 --- a/client/ui/uilogic.h +++ b/client/ui/uilogic.h @@ -16,7 +16,10 @@ #include "models/protocols_model.h" #include "notificationhandler.h" -#include "settings.h" + +class Settings; +class VpnConfigurator; +class ServerController; class AppSettingsLogic; class GeneralSettingsLogic; @@ -50,15 +53,14 @@ class UiLogic : public QObject AUTO_PROPERTY(bool, pageEnabled) AUTO_PROPERTY(int, pagesStackDepth) AUTO_PROPERTY(int, currentPageValue) + AUTO_PROPERTY(QString, dialogConnectErrorText) READONLY_PROPERTY(QObject *, containersModel) READONLY_PROPERTY(QObject *, protocolsModel) - // TODO: review - Q_PROPERTY(QString dialogConnectErrorText READ getDialogConnectErrorText WRITE setDialogConnectErrorText NOTIFY dialogConnectErrorTextChanged) - public: - explicit UiLogic(std::shared_ptr settings, QObject *parent = nullptr); + explicit UiLogic(std::shared_ptr settings, std::shared_ptr configurator, + std::shared_ptr serverController, QObject *parent = nullptr); ~UiLogic(); void showOnStartup(); @@ -108,9 +110,6 @@ class UiLogic : public QObject void shareTempFile(const QString &suggestedName, QString ext, const QString& data); - QString getDialogConnectErrorText() const; - void setDialogConnectErrorText(const QString &dialogConnectErrorText); - signals: void dialogConnectErrorTextChanged(); @@ -127,9 +126,6 @@ class UiLogic : public QObject void raise(); void toggleLogPanel(); -private: - QString m_dialogConnectErrorText; - private slots: // containers - INOUT arg void installServer(QMap &containers); @@ -214,7 +210,10 @@ private slots: VpnConnection* m_vpnConnection; QThread m_vpnConnectionThread; + std::shared_ptr m_settings; + std::shared_ptr m_configurator; + std::shared_ptr m_serverController; NotificationHandler* m_notificationHandler; diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index baee8933a..d3b7faacf 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -29,8 +29,12 @@ #include "utils.h" #include "vpnconnection.h" -VpnConnection::VpnConnection(std::shared_ptr settings, QObject* parent) : QObject(parent), - m_settings(settings) +VpnConnection::VpnConnection(std::shared_ptr settings, + std::shared_ptr configurator, + std::shared_ptr serverController, QObject* parent) : QObject(parent), + m_settings(settings), + m_configurator(configurator), + m_serverController(serverController) { } @@ -214,18 +218,18 @@ QString VpnConnection::createVpnConfigurationForProto(int serverIndex, QString configData; if (lastVpnConfig.contains(proto)) { configData = lastVpnConfig.value(proto); - configData = VpnConfigurator::processConfigWithLocalSettings(serverIndex, container, proto, configData); + configData = m_configurator->processConfigWithLocalSettings(serverIndex, container, proto, configData); qDebug() << "VpnConnection::createVpnConfiguration: using saved config for" << ProtocolProps::protoToString(proto); } else { qDebug() << "VpnConnection::createVpnConfiguration: gen new config for" << ProtocolProps::protoToString(proto); - configData = VpnConfigurator::genVpnProtocolConfig(credentials, + configData = m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, proto, &e); QString configDataBeforeLocalProcessing = configData; - configData = VpnConfigurator::processConfigWithLocalSettings(serverIndex, container, proto, configData); + configData = m_configurator->processConfigWithLocalSettings(serverIndex, container, proto, configData); if (errorCode && e) { @@ -271,7 +275,7 @@ QJsonObject VpnConnection::createVpnConfiguration(int serverIndex, Proto proto = ContainerProps::defaultProtocol(container); vpnConfiguration[config_key::vpnproto] = ProtocolProps::protoToString(proto); - auto dns = VpnConfigurator::getDnsForConfig(serverIndex); + auto dns = m_configurator->getDnsForConfig(serverIndex); vpnConfiguration[config_key::dns1] = dns.first; vpnConfiguration[config_key::dns2] = dns.second; @@ -345,7 +349,7 @@ void VpnConnection::connectToVpn(int serverIndex, connect(m_vpnProtocol.data(), SIGNAL(connectionStateChanged(VpnProtocol::VpnConnectionState)), this, SLOT(onConnectionStateChanged(VpnProtocol::VpnConnectionState))); connect(m_vpnProtocol.data(), SIGNAL(bytesChanged(quint64, quint64)), this, SLOT(onBytesChanged(quint64, quint64))); - ServerController::disconnectFromHost(credentials); + m_serverController->disconnectFromHost(credentials); e = m_vpnProtocol.data()->start(); if (e) emit VpnProtocol::Error; diff --git a/client/vpnconnection.h b/client/vpnconnection.h index 86d096b6a..18446e744 100644 --- a/client/vpnconnection.h +++ b/client/vpnconnection.h @@ -14,6 +14,9 @@ #include "core/ipcclient.h" #endif +class VpnConfigurator; +class ServerController; + using namespace amnezia; class VpnConnection : public QObject @@ -21,7 +24,9 @@ class VpnConnection : public QObject Q_OBJECT public: - explicit VpnConnection(std::shared_ptr settings, QObject* parent = nullptr); + explicit VpnConnection(std::shared_ptr settings, + std::shared_ptr configurator, + std::shared_ptr serverController, QObject* parent = nullptr); ~VpnConnection() override; static QString bytesPerSecToText(quint64 bytes); @@ -74,6 +79,9 @@ protected slots: private: std::shared_ptr m_settings; + std::shared_ptr m_configurator; + std::shared_ptr m_serverController; + QJsonObject m_vpnConfiguration; QJsonObject m_routeMode; QString m_remoteAddress; From aed688224b1bd29547091a8068553588220f5c28 Mon Sep 17 00:00:00 2001 From: pokamest Date: Fri, 26 Aug 2022 00:35:03 +0300 Subject: [PATCH 19/20] App refactoring finished --- client/amnezia_application.cpp | 31 +++++++++++---------- client/amnezia_application.h | 12 ++++---- client/client.pro | 3 +- client/secure_qsettings.cpp | 6 ++++ client/secure_qsettings.h | 4 +++ client/settings.cpp | 50 ---------------------------------- client/settings.h | 4 +-- 7 files changed, 35 insertions(+), 75 deletions(-) diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp index a0776c309..585050e23 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -36,15 +36,14 @@ #include "ui/pages_logic/protocols/ShadowSocksLogic.h" -AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecondary, - SingleApplication::Options options, int timeout, const QString &userData): - #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) - QAPPLICATION_CLASS(argc, argv); - #else - SingleApplication(argc, argv, allowSecondary, options, timeout, userData) - #endif - - +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + AmneziaApplication::AmneziaApplication(int &argc, char *argv[]): + AMNEZIA_BASE_CLASS(argc, argv) +#else + AmneziaApplication::AmneziaApplication(int &argc, char *argv[], bool allowSecondary, + SingleApplication::Options options, int timeout, const QString &userData): + SingleApplication(argc, argv, allowSecondary, options, timeout, userData) +#endif { setQuitOnLastWindowClosed(false); m_settings = std::shared_ptr(new Settings); @@ -59,6 +58,9 @@ AmneziaApplication::~AmneziaApplication() QObject::disconnect(m_uiLogic, 0,0,0); delete m_uiLogic; + + delete m_protocolProps; + delete m_containerProps; } void AmneziaApplication::init() @@ -112,7 +114,7 @@ void AmneziaApplication::init() if (m_parser.isSet("a")) m_uiLogic->showOnStartup(); else emit m_uiLogic->show(); #else - uiLogic->showOnStartup(); + m_uiLogic->showOnStartup(); #endif // TODO - fix @@ -144,7 +146,6 @@ void AmneziaApplication::registerTypes() qRegisterMetaType("PageProtocolLogicBase *"); - declareQmlPageEnum(); declareQmlProtocolEnum(); declareQmlContainerEnum(); @@ -152,11 +153,11 @@ void AmneziaApplication::registerTypes() qmlRegisterType("PageType", 1, 0, "PageType"); qmlRegisterType("QRCodeReader", 1, 0, "QRCodeReader"); - QScopedPointer containerProps(new ContainerProps); - qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", containerProps.get()); + m_containerProps = new ContainerProps; + qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", m_containerProps); - QScopedPointer protocolProps(new ProtocolProps); - qmlRegisterSingletonInstance("ProtocolProps", 1, 0, "ProtocolProps", protocolProps.get()); + m_protocolProps = new ProtocolProps; + qmlRegisterSingletonInstance("ProtocolProps", 1, 0, "ProtocolProps", m_protocolProps); } void AmneziaApplication::loadFonts() diff --git a/client/amnezia_application.h b/client/amnezia_application.h index e0dfbc3a4..c665ffef8 100644 --- a/client/amnezia_application.h +++ b/client/amnezia_application.h @@ -13,13 +13,12 @@ #include "ui/uilogic.h" #include "configurators/vpn_configurator.h" -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + #define AMNEZIA_BASE_CLASS QGuiApplication +#else #define AMNEZIA_BASE_CLASS SingleApplication - #define QAPPLICATION_CLASS QGuiApplication + #define QAPPLICATION_CLASS QApplication #include "singleapplication.h" - //#undef QAPPLICATION_CLASS -#else - #define AMNEZIA_BASE_CLASS QApplication #endif class AmneziaApplication : public AMNEZIA_BASE_CLASS @@ -47,6 +46,9 @@ class AmneziaApplication : public AMNEZIA_BASE_CLASS std::shared_ptr m_configurator; std::shared_ptr m_serverController; + ContainerProps* m_containerProps; + ProtocolProps* m_protocolProps; + QTranslator* m_translator; QCommandLineParser m_parser; diff --git a/client/client.pro b/client/client.pro index 996521d1d..157027554 100644 --- a/client/client.pro +++ b/client/client.pro @@ -2,7 +2,6 @@ QT += widgets core gui network xml remoteobjects quick svg TARGET = AmneziaVPN TEMPLATE = app -#CONFIG += console CONFIG += qtquickcompiler CONFIG += qzxing_multimedia \ @@ -287,7 +286,7 @@ android { } ios { - message("Client ios build") + message("Client iOS build") CONFIG += static CONFIG += file_copies diff --git a/client/secure_qsettings.cpp b/client/secure_qsettings.cpp index 488feb490..547326df1 100644 --- a/client/secure_qsettings.cpp +++ b/client/secure_qsettings.cpp @@ -32,6 +32,8 @@ SecureQSettings::SecureQSettings(const QString &organization, const QString &app QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue) const { + QMutexLocker locker(&mutex); + if (m_cache.contains(key)) { return m_cache.value(key); } @@ -76,6 +78,8 @@ QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue void SecureQSettings::setValue(const QString &key, const QVariant &value) { + QMutexLocker locker(&mutex); + if (encryptionRequired() && encryptedKeys.contains(key)) { if (!getEncKey().isEmpty() && !getEncIv().isEmpty()) { QByteArray decryptedValue; @@ -103,6 +107,8 @@ void SecureQSettings::setValue(const QString &key, const QVariant &value) void SecureQSettings::remove(const QString &key) { + QMutexLocker locker(&mutex); + m_settings.remove(key); m_cache.remove(key); diff --git a/client/secure_qsettings.h b/client/secure_qsettings.h index b36de1eb1..ea6da1060 100644 --- a/client/secure_qsettings.h +++ b/client/secure_qsettings.h @@ -3,6 +3,9 @@ #include #include +#include +#include + constexpr const char* settingsKeyTag = "settingsKeyTag"; constexpr const char* settingsIvTag = "settingsIvTag"; @@ -40,6 +43,7 @@ class SecureQSettings : public QObject const QByteArray magicString { "EncData" }; // Magic keyword used for mark encrypted QByteArray + mutable QMutex mutex; }; #endif // SECUREQSETTINGS_H diff --git a/client/settings.cpp b/client/settings.cpp index 21deb0bd1..58695f60f 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -295,60 +295,10 @@ void Settings::removeVpnSites(RouteMode mode, const QStringList &sites) setVpnSites(mode, sitesMap); } -//void Settings::addVpnForwardSite(const QString &site, const QString &ip) -//{ -// auto sites = vpnForwardSites(); -// QStringList l = sites.value(site).toStringList(); -// if (!l.contains(ip)) { -// l.append(ip); -// setVpnForwardSites(sites); -// } -//} - -//QStringList Settings::getVpnForwardIps() const -//{ -// QStringList ips; -// const QVariantMap &m = vpnForwardSites(); -// for (const QVariant &v : m) { -// ips.append(v.toStringList()); -// } -// ips.removeDuplicates(); -// return ips; -//} - -//void Settings::addVpnExceptSite(const QString &site, const QString &ip) -//{ -// auto sites = vpnExceptSites(); -// QStringList l = sites.value(site).toStringList(); -// if (!l.contains(ip)) { -// l.append(ip); -// setVpnExceptSites(sites); -// } -//} - -//QStringList Settings::getVpnExceptIps() const -//{ -// QStringList ips; -// const QVariantMap &m = vpnExceptSites(); -// for (const QVariant &v : m) { -// ips.append(v.toStringList()); -// } -// ips.removeDuplicates(); -// return ips; -//} - QString Settings::primaryDns() const { return m_settings.value("Conf/primaryDns", cloudFlareNs1).toString(); } QString Settings::secondaryDns() const { return m_settings.value("Conf/secondaryDns", cloudFlareNs2).toString(); } -//void Settings::setServerCredentials(const ServerCredentials &credentials) -//{ -// setServerName(credentials.hostName); -// setServerPort(credentials.port); -// setUserName(credentials.userName); -// setPassword(credentials.password); -//} - ServerCredentials Settings::defaultServerCredentials() const { return serverCredentials(defaultServerIndex()); diff --git a/client/settings.h b/client/settings.h index fc5753297..aa32cb0eb 100644 --- a/client/settings.h +++ b/client/settings.h @@ -8,7 +8,6 @@ #include #include #include -#include #include "core/defs.h" #include "containers/containers_defs.h" @@ -27,7 +26,6 @@ class Settings : public QObject ServerCredentials defaultServerCredentials() const; ServerCredentials serverCredentials(int index) const; - //void setServerCredentials(const ServerCredentials &credentials); QJsonArray serversArray() const { return QJsonDocument::fromJson(m_settings.value("Servers/serversList").toByteArray()).array(); } void setServersArray(const QJsonArray &servers) { m_settings.setValue("Servers/serversList", QJsonDocument(servers).toJson()); } @@ -117,7 +115,7 @@ class Settings : public QObject private: SecureQSettings m_settings; - QMutex m_mutex; + }; #endif // SETTINGS_H From aae1da3aa81a1207f27e6fc6a96dbb75b5b2fd2f Mon Sep 17 00:00:00 2001 From: pokamest Date: Fri, 26 Aug 2022 00:58:24 +0300 Subject: [PATCH 20/20] Cleanup code --- client/amnezia_application.h | 2 +- client/secure_qsettings.cpp | 2 -- client/settings.cpp | 4 ---- client/ui/pages_logic/ShareConnectionLogic.cpp | 2 -- client/ui/pages_logic/StartPageLogic.cpp | 11 ----------- client/ui/pages_logic/protocols/ShadowSocksLogic.cpp | 1 - client/ui/systemtray_notificationhandler.cpp | 1 - client/ui/uilogic.cpp | 10 ++-------- client/utils.cpp | 1 - client/vpnconnection.cpp | 6 ------ 10 files changed, 3 insertions(+), 37 deletions(-) diff --git a/client/amnezia_application.h b/client/amnezia_application.h index c665ffef8..6d0ef5d2d 100644 --- a/client/amnezia_application.h +++ b/client/amnezia_application.h @@ -14,7 +14,7 @@ #include "configurators/vpn_configurator.h" #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) - #define AMNEZIA_BASE_CLASS QGuiApplication + #define AMNEZIA_BASE_CLASS QApplication #else #define AMNEZIA_BASE_CLASS SingleApplication #define QAPPLICATION_CLASS QApplication diff --git a/client/secure_qsettings.cpp b/client/secure_qsettings.cpp index 547326df1..828369796 100644 --- a/client/secure_qsettings.cpp +++ b/client/secure_qsettings.cpp @@ -13,8 +13,6 @@ SecureQSettings::SecureQSettings(const QString &organization, const QString &app m_settings(organization, application, parent), encryptedKeys({"Servers/serversList"}) { - qDebug() << "SecureQSettings::SecureQSettings CTOR"; - bool encrypted = m_settings.value("Conf/encrypted").toBool(); // convert settings to encrypted for if updated to >= 2.1.0 diff --git a/client/settings.cpp b/client/settings.cpp index 58695f60f..6e470a338 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -2,7 +2,6 @@ #include "settings.h" #include "utils.h" -#include #include "containers/containers_defs.h" const char Settings::cloudFlareNs1[] = "1.1.1.1"; @@ -13,8 +12,6 @@ Settings::Settings(QObject* parent) : QObject(parent), m_settings(ORGANIZATION_NAME, APPLICATION_NAME, this) { - qDebug() << "Settings::Settings()" << this; -// qDebug() << "Settings::Settings()" << m_settings.fileName(); // Import old settings if (serversCount() == 0) { QString user = m_settings.value("Server/userName").toString(); @@ -181,7 +178,6 @@ void Settings::clearLastConnectionConfig(int serverIndex, DockerContainer contai QJsonObject c = protocolConfig(serverIndex, container, proto); c.remove(config_key::last_config); setProtocolConfig(serverIndex, container, proto, c); - qDebug() << "Settings::clearLastConnectionConfig for" << serverIndex << container << proto; } bool Settings::haveAuthData(int serverIndex) const diff --git a/client/ui/pages_logic/ShareConnectionLogic.cpp b/client/ui/pages_logic/ShareConnectionLogic.cpp index 2e4404984..6367722ac 100644 --- a/client/ui/pages_logic/ShareConnectionLogic.cpp +++ b/client/ui/pages_logic/ShareConnectionLogic.cpp @@ -238,8 +238,6 @@ void ShareConnectionLogic::onPushButtonShareIkev2GenerateClicked() DockerContainer container = uiLogic()->selectedDockerContainer; ServerCredentials credentials = m_settings->serverCredentials(serverIndex); - //const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container); - Ikev2Configurator::ConnectionData connData = m_configurator->ikev2Configurator->prepareIkev2Config(credentials, container); QString cfg = m_configurator->ikev2Configurator->genIkev2Config(connData); diff --git a/client/ui/pages_logic/StartPageLogic.cpp b/client/ui/pages_logic/StartPageLogic.cpp index b7b5907e0..4fb00f6f6 100644 --- a/client/ui/pages_logic/StartPageLogic.cpp +++ b/client/ui/pages_logic/StartPageLogic.cpp @@ -49,8 +49,6 @@ void StartPageLogic::onUpdatePage() void StartPageLogic::onPushButtonConnect() { -// uiLogic()->goToPage(Page::NewServer); -// return; if (pushButtonConnectKeyChecked()){ if (lineEditIpText().isEmpty() || lineEditLoginText().isEmpty() || @@ -67,7 +65,6 @@ void StartPageLogic::onPushButtonConnect() return; } } - qDebug() << "UiLogic::onPushButtonConnect checking new server"; ServerCredentials serverCredentials; serverCredentials.hostName = lineEditIpText(); @@ -152,13 +149,6 @@ bool StartPageLogic::importConnection(const QJsonObject &profile) credentials.userName = profile.value(config_key::userName).toString(); credentials.password = profile.value(config_key::password).toString(); -// qDebug() << QString("Added server %3@%1:%2"). -// arg(credentials.hostName). -// arg(credentials.port). -// arg(credentials.userName); - - //qDebug() << QString("Password") << credentials.password; - if (credentials.isValid() || profile.contains(config_key::containers)) { m_settings->addServer(profile); m_settings->setDefaultServer(m_settings->serversCount() - 1); @@ -208,7 +198,6 @@ bool StartPageLogic::importConnectionFromCode(QString code) bool StartPageLogic::importConnectionFromQr(const QByteArray &data) { - qDebug() << "StartPageLogic::importConnectionFromQr" << data; QJsonObject dataObj = QJsonDocument::fromJson(data).object(); if (!dataObj.isEmpty()) { return importConnection(dataObj); diff --git a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp index e26efac1e..1d5da9366 100644 --- a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp +++ b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp @@ -47,7 +47,6 @@ QJsonObject ShadowSocksLogic::getProtocolConfigFromPage(QJsonObject oldConfig) void ShadowSocksLogic::onPushButtonSaveClicked() { QJsonObject protocolConfig = m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::ShadowSocks); - //protocolConfig = getShadowSocksConfigFromPage(protocolConfig); QJsonObject containerConfig = m_settings->containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); QJsonObject newContainerConfig = containerConfig; diff --git a/client/ui/systemtray_notificationhandler.cpp b/client/ui/systemtray_notificationhandler.cpp index 21e24ac19..e142caf54 100644 --- a/client/ui/systemtray_notificationhandler.cpp +++ b/client/ui/systemtray_notificationhandler.cpp @@ -75,7 +75,6 @@ void SystemTrayNotificationHandler::onTrayActivated(QSystemTrayIcon::ActivationR void SystemTrayNotificationHandler::setTrayState(VpnProtocol::VpnConnectionState state) { - qDebug() << "SystemTrayNotificationHandler::setTrayState" << state; QString resourcesPath = ":/images/tray/%1"; switch (state) { diff --git a/client/ui/uilogic.cpp b/client/ui/uilogic.cpp index 555c6bdc1..f3d45577a 100644 --- a/client/ui/uilogic.cpp +++ b/client/ui/uilogic.cpp @@ -147,14 +147,12 @@ void UiLogic::initalizeUiLogic() } }); if (!AndroidController::instance()->initialize()) { - qDebug() << QString("Init failed") ; + qCritical() << QString("Init failed") ; emit VpnProtocol::Error; return; } #endif - qDebug() << "UiLogic::initalizeUiLogic()"; - m_notificationHandler = NotificationHandler::create(qmlRoot()); connect(m_vpnConnection, &VpnConnection::connectionStateChanged, m_notificationHandler, &NotificationHandler::setConnectionState); @@ -235,7 +233,6 @@ void UiLogic::keyPressEvent(Qt::Key key) #endif case Qt::Key_C: qDebug().noquote() << "Def server" << m_settings->defaultServerIndex() << m_settings->defaultContainerName(m_settings->defaultServerIndex()); - //qDebug().noquote() << QJsonDocument(m_settings->containerConfig(m_settings->defaultServerIndex(), m_settings->defaultContainer(m_settings->defaultServerIndex()))).toJson(); qDebug().noquote() << QJsonDocument(m_settings->defaultServer()).toJson(); break; case Qt::Key_A: @@ -578,7 +575,7 @@ PageProtocolLogicBase *UiLogic::protocolLogic(Proto p) PageProtocolLogicBase *logic = m_protocolLogicMap.value(p); if (logic) return logic; else { - qDebug() << "UiLogic::protocolLogic Warning: logic missing for" << p; + qCritical() << "UiLogic::protocolLogic Warning: logic missing for" << p; return new PageProtocolLogicBase(this); } } @@ -623,13 +620,11 @@ void UiLogic::saveTextFile(const QString& desc, const QString& suggestedName, QS QUrl::fromLocalFile(docDir), "*" + ext); #endif - qDebug() << "UiLogic::saveTextFile" << fileName; if (fileName.isEmpty()) return; #ifdef AMNEZIA_DESKTOP QFile save(fileName.toLocalFile()); #else - qDebug() << "UiLogic::saveTextFile" << QQmlFile::urlToLocalFileOrQrc(fileName); QFile save(QQmlFile::urlToLocalFileOrQrc(fileName)); #endif @@ -672,7 +667,6 @@ void UiLogic::shareTempFile(const QString &suggestedName, QString ext, const QSt if (!fileName.endsWith(ext)) fileName.append(ext); QFile::remove(fileName); - qDebug() << "UiLogic::shareTempFile" << fileName; QFile save(fileName); save.open(QIODevice::WriteOnly); diff --git a/client/utils.cpp b/client/utils.cpp index 046d582cd..0e4c14037 100644 --- a/client/utils.cpp +++ b/client/utils.cpp @@ -121,7 +121,6 @@ QString Utils::getIPAddress(const QString& host) QList adresses = QHostInfo::fromName(host).addresses(); if (!adresses.isEmpty()) { - qDebug() << "Resolved address for" << host << adresses.first().toString(); return adresses.first().toString(); } qDebug() << "Unable to resolve address for " << host; diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index d3b7faacf..6e117ce43 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -219,11 +219,8 @@ QString VpnConnection::createVpnConfigurationForProto(int serverIndex, if (lastVpnConfig.contains(proto)) { configData = lastVpnConfig.value(proto); configData = m_configurator->processConfigWithLocalSettings(serverIndex, container, proto, configData); - - qDebug() << "VpnConnection::createVpnConfiguration: using saved config for" << ProtocolProps::protoToString(proto); } else { - qDebug() << "VpnConnection::createVpnConfiguration: gen new config for" << ProtocolProps::protoToString(proto); configData = m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, proto, &e); @@ -363,8 +360,6 @@ QString VpnConnection::bytesPerSecToText(quint64 bytes) void VpnConnection::disconnectFromVpn() { - // qDebug() << "Disconnect from VPN 1"; - #ifdef AMNEZIA_DESKTOP if (IpcClient::Interface()) { IpcClient::Interface()->flushDns(); @@ -385,7 +380,6 @@ void VpnConnection::disconnectFromVpn() return; } m_vpnProtocol.data()->stop(); - // qDebug() << "Disconnect from VPN 2"; } VpnProtocol::VpnConnectionState VpnConnection::connectionState()