Merge branch 'dev' into AVP-01-011

This commit is contained in:
pokamest 2022-08-27 18:31:20 +03:00
commit ed6a417d7e
223 changed files with 4072 additions and 2096 deletions

3
.gitmodules vendored
View file

@ -25,3 +25,6 @@
[submodule "client/3rd/CocoaLumberjack"]
path = client/3rd/CocoaLumberjack
url = https://github.com/CocoaLumberjack/CocoaLumberjack.git
[submodule "client/3rd/qtkeychain"]
path = client/3rd/qtkeychain
url = https://github.com/frankosterfeld/qtkeychain.git

View file

@ -1,5 +1,3 @@
language: cpp
branches:
only:
- master
@ -10,135 +8,328 @@ jobs:
include:
- name: MacOS
os: osx
osx_image: xcode12.5
osx_image: xcode13.4
language: cpp
env:
- PATH=/usr/local/opt/ccache/libexec:$PATH
- QT_VERSION=5.15.2
- QIF_VERSION=4.1
- QIF_VERSION=4.4
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/clang_64/bin
- QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/$QIF_VERSION/bin
install:
- |
if [ ! -f $QT_BIN_DIR/qmake ]; then \
brew install p7zip ccache && \
python3 -m pip install --upgrade pip && \
pip install -U aqtinstall requests py7zr && \
pip show aqtinstall && \
aqt install-qt mac desktop $QT_VERSION clang_64 -m all -O $HOME/Qt && \
aqt install-tool mac desktop tools_ifw -O $HOME/Qt ; \
fi
script:
- |
if [ ! -f $HOME/Qt/$QT_VERSION/clang_64/bin/qmake ]; then \
brew install p7zip && \
python3 -m pip install --upgrade pip && \
pip install -U aqtinstall requests py7zr && \
pip show aqtinstall && \
python3 -m aqt install --outputdir $HOME/Qt $QT_VERSION mac desktop clang_64 -m qtbase && \
python3 -m aqt tool --outputdir $HOME/Qt mac tools_ifw $QIF_VERSION qt.tools.ifw.${QIF_VERSION/./};
fi
- bash deploy/build_macos.sh
after_script:
- ccache --show-stats
deploy:
provider: releases
token: $GH_TOKEN
skip_cleanup: true
cleanup: false
file:
- "AmneziaVPN_unsigned.dmg"
- "AmneziaVPN.dmg"
on:
tags: true
branch: master
cache:
- ccache
- directories:
- $HOME/Qt
- $HOME/Library/Caches/Homebrew
# ------------------------------------------------------
- name: Windows_x64
os: windows
language: cpp
env:
- PATH=/c/Python39:/c/Python39/Scripts:$PATH
- QT_VERSION=5.14.2
- QIF_VERSION=4.1
- QT_BIN_DIR="c:\\Qt\\$QT_VERSION\\msvc2017_64\\bin"
- QT_VERSION=5.15.2
- QIF_VERSION=4.4
- QT_BIN_DIR="c:\\Qt\\$QT_VERSION\\msvc2019_64\\bin"
- QIF_BIN_DIR="c:\\Qt\\Tools\\QtInstallerFramework\\${QIF_VERSION}\\bin"
- BUILD_ARCH=64
before_install:
- if [ ! -f /C/Qt/$QT_VERSION/msvc2017_64/bin/qmake ]; then choco install python --version 3.9.1; fi
script:
- dir "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build"
- dir "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools"
- MSVC_PATH_WIN="C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community"
- MSVC_PATH="/C/Program Files (x86)/Microsoft Visual Studio/2019/Community"
install:
- if [ ! -f "$MSVC_PATH/VC/Auxiliary/Build/vcvars64.bat" ]; then choco install --ignorepackagecodes --no-progress -y visualstudio2019buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Component.VC.ATLMFC --includeRecommended --nocache --installPath $MSVC_PATH_WIN"; fi
- if [ ! -f /C/Qt/$QT_VERSION/msvc2019_64/bin/qmake ]; then choco install python --version 3.9.1; fi
- |
if [ ! -f /C/Qt/$QT_VERSION/msvc2017_64/bin/qmake ]; then \
if [ ! -f /C/Qt/$QT_VERSION/msvc2019_64/bin/qmake ]; then \
python -m pip install --upgrade pip && \
pip3 install -U aqtinstall requests py7zr && \
pip3 show aqtinstall && \
python -m aqt install --outputdir /C/Qt $QT_VERSION windows desktop win64_msvc2017_64 -m qtbase && \
python -m aqt tool --outputdir /C/Qt windows tools_ifw $QIF_VERSION qt.tools.ifw.${QIF_VERSION/./}; \
aqt install-qt windows desktop $QT_VERSION win64_msvc2019_64 -m all -O /C/Qt && \
aqt install-tool windows desktop tools_ifw -O /C/Qt ; \
fi
script:
- echo set BUILD_ARCH=$BUILD_ARCH > winbuild.bat
- echo set QT_BIN_DIR="$QT_BIN_DIR" >> winbuild.bat
- echo set QIF_BIN_DIR="$QIF_BIN_DIR" >> winbuild.bat
- echo call \""C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\Auxiliary\\Build\\vcvars${BUILD_ARCH}.bat\"" >> winbuild.bat
- echo call \""C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\Common7\\Tools\\VsDevCmd.bat\" -arch=amd64" >> winbuild.bat
- echo set WIN_CERT_PW=$WIN_CERT_PW >> winbuild.bat
- echo call \""%MSVC_PATH_WIN%\\VC\\Auxiliary\\Build\\vcvars${BUILD_ARCH}.bat\"" >> winbuild.bat
- echo call \""%MSVC_PATH_WIN%\\Common7\\Tools\\VsDevCmd.bat\" -arch=amd64" >> winbuild.bat
- echo call deploy\\build_windows.bat >> winbuild.bat
- cmd //c winbuild.bat
deploy:
provider: releases
token: $GH_TOKEN
skip_cleanup: true
cleanup: false
file:
- "AmneziaVPN_x64.exe"
on:
tags: true
branch: master
cache:
directories:
- /C/Qt
- $MSVC_PATH
# ------------------------------------------------------
- name: Windows_x32
os: windows
language: cpp
env:
- PATH=/c/Python39:/c/Python39/Scripts:$PATH
- QT_VERSION=5.14.2
- QIF_VERSION=4.1
- QT_BIN_DIR="c:\\Qt\\${QT_VERSION}\\msvc2017\\bin"
- QT_VERSION=5.15.2
- QIF_VERSION=4.4
- QT_BIN_DIR="c:\\Qt\\${QT_VERSION}\\msvc2019\\bin"
- QIF_BIN_DIR="c:\\Qt\\Tools\\QtInstallerFramework\\${QIF_VERSION}\\bin"
- BUILD_ARCH=32
- MSVC_PATH_WIN="C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community"
- MSVC_PATH="/C/Program Files (x86)/Microsoft Visual Studio/2019/Community"
before_install:
- if [ ! -f /C/Qt/$QT_VERSION/msvc2017/bin/qmake ]; then choco install python --version 3.9.1; fi
script:
- dir "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build"
- dir "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools"
install:
- if [ ! -f "$MSVC_PATH/VC/Auxiliary/Build/vcvars64.bat" ]; then choco install --ignorepackagecodes --no-progress -y visualstudio2019buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Component.VC.ATLMFC --includeRecommended --nocache --installPath $MSVC_PATH_WIN"; fi
- if [ ! -f /C/Qt/$QT_VERSION/msvc2019/bin/qmake ]; then choco install python --version 3.9.1; fi
- |
if [ ! -f /C/Qt/$QT_VERSION/msvc2017/bin/qmake ]; then \
if [ ! -f /C/Qt/$QT_VERSION/msvc2019/bin/qmake ]; then \
python -m pip install --upgrade pip && \
pip3 install -U aqtinstall requests py7zr && \
pip3 show aqtinstall && \
python -m aqt install --outputdir /C/Qt $QT_VERSION windows desktop win32_msvc2017 -m qtbase && \
python -m aqt tool --outputdir /C/Qt windows tools_ifw $QIF_VERSION qt.tools.ifw.${QIF_VERSION/./}; \
aqt install-qt windows desktop $QT_VERSION win32_msvc2019 -m all -O /C/Qt && \
aqt install-tool windows desktop tools_ifw -O /C/Qt ; \
fi
- echo call \""C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\Common7\\Tools\\VsDevCmd.bat\"" > winbuild.bat
- echo set BUILD_ARCH=$BUILD_ARCH >> winbuild.bat
script:
- echo set BUILD_ARCH=$BUILD_ARCH > winbuild.bat
- echo set QT_BIN_DIR="$QT_BIN_DIR" >> winbuild.bat
- echo set QIF_BIN_DIR="$QIF_BIN_DIR" >> winbuild.bat
- echo call \""C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\Auxiliary\\Build\\vcvars${BUILD_ARCH}.bat\"" >> winbuild.bat
- echo set WIN_CERT_PW=$WIN_CERT_PW >> winbuild.bat
- echo call \""%MSVC_PATH_WIN%\\VC\\Auxiliary\\Build\\vcvars${BUILD_ARCH}.bat\"" >> winbuild.bat
- echo call \""%MSVC_PATH_WIN%\\Common7\\Tools\\VsDevCmd.bat\"" >> winbuild.bat
- echo call deploy\\build_windows.bat >> winbuild.bat
- cmd //c winbuild.bat
deploy:
provider: releases
token: $GH_TOKEN
skip_cleanup: true
cleanup: false
file:
- "AmneziaVPN_x32.exe"
on:
tags: true
branch: master
deploy:
skip_cleanup: true
cache:
directories:
- /C/Qt
- $MSVC_PATH
# ------------------------------------------------------
- name: Linux
os: linux
dist: focal
addons:
apt:
packages:
- p7zip
- python3
- python3-pip
- libgl-dev
- mesa-common-dev
- libpulse-dev
env:
- QT_VERSION=5.15.2
- QIF_VERSION=4.4
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/gcc_64/bin
- QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/$QIF_VERSION/bin
install:
- |
if [ ! -f $QT_BIN_DIR/qmake ]; then \
python3 -m pip install --user $(whoami) --upgrade pip && \
export PATH=$HOME/.local/bin:$PATH && \
python3 -m pip install -U aqtinstall requests py7zr && \
python3 -m pip show aqtinstall && \
python3 -m aqt install-qt linux desktop $QT_VERSION gcc_64 -m all -O $HOME/Qt && \
python3 -m aqt install-tool linux desktop tools_ifw -O $HOME/Qt ; \
fi
script:
- bash deploy/build_linux.sh
after_script:
- ccache --show-stats
deploy:
provider: releases
token: $GH_TOKEN
cleanup: false
file:
- "AmneziaVPN.bundle"
on:
tags: true
branch: master
cache:
- ccache
- directories:
- $HOME/Qt
# ------------------------------------------------------
- name: Android
os: linux
language: android
dist: xenial
addons:
apt:
packages:
- p7zip
- python3
- python3-pip
android:
components:
# Uncomment the lines below if you want to
# use the latest revision of Android SDK Tools
# - tools
# - platform-tools
# The BuildTools version used by your project
- build-tools-30.0.2
# The SDK version used to compile your project
- android-30
# Additional components
- extra
- extra-google-google_play_services
- extra-google-m2repository
- extra-android-m2repository
env:
- QT_VERSION=5.15.2
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/android/bin
- USE_ANDROID_NDK_VERSION=21d
- ANDROID_NDK_HOME=$HOME/NDK
install:
- |
if [ ! -f $QT_BIN_DIR/qmake ]; then \
export PATH=$HOME/.local/bin:$PATH && \
python3 -m pip install -U aqtinstall requests py7zr && \
python3 -m pip show aqtinstall && \
python3 -m aqt install-qt linux android $QT_VERSION android_armv7 -m all -O $HOME/Qt && \
python3 -m aqt install-qt linux android $QT_VERSION android_arm64_v8a -m all -O $HOME/Qt && \
python3 -m aqt install-qt linux android $QT_VERSION android_x86_64 -m all -O $HOME/Qt && \
python3 -m aqt install-qt linux android $QT_VERSION android_x86 -m all -O $HOME/Qt ; \
fi
- |
export TERM=dumb &&
curl -L https://dl.google.com/android/repository/android-ndk-r${USE_ANDROID_NDK_VERSION}-linux-x86_64.zip -O &&
unzip ./android-ndk-r${USE_ANDROID_NDK_VERSION}-linux-x86_64.zip > /dev/null &&
rm android-ndk-r${USE_ANDROID_NDK_VERSION}-linux-x86_64.zip &&
export ANDROID_NDK_HOME=`pwd`/android-ndk-r${USE_ANDROID_NDK_VERSION} &&
export LOCAL_ANDROID_NDK_HOME="$ANDROID_NDK_HOME" &&
export LOCAL_ANDROID_NDK_HOST_PLATFORM="linux-x86_64" &&
export PATH=$PATH:${ANDROID_NDK_HOME} &&
env
script:
- bash deploy/build_android.sh
after_script:
- ccache --show-stats
deploy:
provider: releases
token: $GH_TOKEN
cleanup: false
file:
- "AmneziaVPN.aab"
on:
tags: true
branch: master
cache:
- ccache
- directories:
- $HOME/Qt
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
- $HOME/.android/build-cache
- $ANDROID_NDK_HOME
# ------------------------------------------------------
- name: iOS
os: osx
osx_image: xcode13.4
language: cpp
env:
- PATH=/usr/local/opt/ccache/libexec:~/go/bin:$PATH
- QT_VERSION=5.15.2
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/ios/bin
- QT_IOS_BIN=$QT_BIN_DIR
install:
- |
if [ ! -f $QT_BIN_DIR/qmake ]; then \
brew install p7zip ccache && \
python3 -m pip install --upgrade pip && \
pip install -U aqtinstall requests py7zr && \
pip show aqtinstall && \
aqt install-qt mac ios $QT_VERSION -m all -O $HOME/Qt ; \
fi
- brew install golang
- go install golang.org/x/mobile/cmd/gomobile@latest
- gomobile init
script:
- bash deploy/build_ios.sh
after_script:
- ccache --show-stats
cache:
- ccache
- directories:
- $HOME/Qt
- $HOME/Library/Caches/Homebrew
before_cache:
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then brew cleanup; fi
# Cache only .git files under "/usr/local/Homebrew" so "brew update" does not take 5min every build
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then find /usr/local/Homebrew \! -regex ".+\.git.+" -delete; fi
cache:
directories:
- $HOME/Qt
- /C/Qt
- $HOME/Library/Caches/Homebrew

View file

@ -20,8 +20,6 @@ AmneziaVPN uses a number of open source projects to work:
- [OpenVPN](https://openvpn.net/)
- [ShadowSocks](https://shadowsocks.org/)
- [Qt](https://www.qt.io/)
- [EasyRSA](https://github.com/OpenVPN/easy-rsa) - part of OpenVPN
- [CygWin](https://www.cygwin.com/) - only for Windiws, used for launching EasyRSA scripts
- [QtSsh](https://github.com/jaredtao/QtSsh) - forked form Qt Creator
- and more...

View file

@ -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

View file

@ -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 <QObject>
#include <memory>
#include <openssl/aes.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#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

View file

@ -0,0 +1,84 @@
/**
* 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 <QObject>
#include <memory>
#include <openssl/aes.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#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);
QByteArray generateSecureRandomBytes(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

View file

@ -0,0 +1,45 @@
#ifndef QCRYPTOERROR_H
#define QCRYPTOERROR_H
#include <QObject>
#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<quint8, QString> lastError() const
{
return QPair<quint8, QString>(m_currentErrorCode, m_errorSummary);
}
private:
quint8 m_currentErrorCode;
QString m_errorSummary;
};
}
#endif // QCRYPTOERROR_H

View file

@ -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 <QFile>
#include <QObject>
#include <memory>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#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

View file

@ -0,0 +1,9 @@
#ifndef QSIMPLECRYPTO_GLOBAL_H
#define QSIMPLECRYPTO_GLOBAL_H
#include <QtCore/qglobal.h>
#include <stdexcept>
#define QSIMPLECRYPTO_EXPORT
#endif // QSIMPLECRYPTO_GLOBAL_H

View file

@ -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 <QMap>
#include <QObject>
#include <memory>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#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<QByteArray, QByteArray>& 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

View file

@ -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 <QDir>
#include <QFile>
#include <QFileInfo>
#include <memory>
#include <openssl/err.h>
#include <openssl/x509_vfy.h>
#include <openssl/x509v3.h>
#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

View file

@ -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<EVP_CIPHER_CTX, void (*)(EVP_CIPHER_CTX*)> 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<unsigned char[]> 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<unsigned char*>(key.data()), reinterpret_cast<unsigned char*>(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<unsigned char*>(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<const unsigned char*>(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<unsigned char*>(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<char*>(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<EVP_CIPHER_CTX, void (*)(EVP_CIPHER_CTX*)> 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<unsigned char[]> 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<unsigned char*>(key.data()), reinterpret_cast<unsigned char*>(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<unsigned char*>(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<const unsigned char*>(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<unsigned char*>(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<char*>(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<EVP_CIPHER_CTX, void (*)(EVP_CIPHER_CTX*)> 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<unsigned char[]> 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<unsigned char*>(key.data()), reinterpret_cast<unsigned char*>(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<unsigned char*>(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<const unsigned char*>(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<unsigned char*>(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<char*>(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<EVP_CIPHER_CTX, void (*)(EVP_CIPHER_CTX*)> 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<unsigned char[]> 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<unsigned char*>(key.data()), reinterpret_cast<unsigned char*>(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<unsigned char*>(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<unsigned char*>(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<const unsigned char*>(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<char*>(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();
}

View file

@ -0,0 +1,193 @@
/**
* 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<char*>(arr), 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<char*>(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<EVP_CIPHER_CTX, void (*)(EVP_CIPHER_CTX*)> 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<unsigned char*>(key.data());
unsigned char* m_iv = reinterpret_cast<unsigned char*>(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<unsigned char[]> 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<unsigned char*>(salt.data()), reinterpret_cast<unsigned char*>(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<const unsigned char*>(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<char*>(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<EVP_CIPHER_CTX, void (*)(EVP_CIPHER_CTX*)> 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<unsigned char*>(key.data());
unsigned char* m_iv = reinterpret_cast<unsigned char*>(iv.data());
/* Set data length */
int plainTextLength(data.size());
int finalLength = 0;
/* Initialize plainText. Here decrypted data will be stored */
std::unique_ptr<unsigned char[]> 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<const unsigned char*>(salt.data()), reinterpret_cast<const unsigned char*>(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<const unsigned char*>(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<char*>(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();
}

View file

@ -0,0 +1,6 @@
#include "include/QCryptoError.h"
QSimpleCrypto::QCryptoError::QCryptoError(QObject* parent)
: QObject(parent)
{
}

View file

@ -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<BIGNUM, void (*)(BIGNUM*)> 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<BIO, void (*)(BIO*)> 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<BIO, void (*)(BIO*)> 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<unsigned char*>(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<BIO, void (*)(BIO*)> 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<BIO, void (*)(BIO*)> 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<unsigned char[]> 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<unsigned char*>(plainText.data()), cipherText.get(), rsa, padding);
} else if (encryptType == PrivateDecrypt) {
result = RSA_private_encrypt(plainText.size(), reinterpret_cast<unsigned char*>(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<char*>(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<unsigned char[]> 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<unsigned char*>(cipherText.data()), plainText.get(), rsa, padding);
} else if (decryptType == PrivateDecrypt) {
result = RSA_private_decrypt(RSA_size(rsa), reinterpret_cast<unsigned char*>(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<char*>(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 "";
}
}

View file

@ -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<BIO, void (*)(BIO*)> 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<BIO, void (*)(BIO*)> 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<X509_STORE_CTX, void (*)(X509_STORE_CTX*)> 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<QByteArray, QByteArray>& 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<EVP_PKEY, void (*)(EVP_PKEY*)> 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<QByteArray, QByteArray> 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<const unsigned char*>(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<BIO, void (*)(BIO*)> 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;
}
}

View file

@ -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;
}

1
client/3rd/qtkeychain Submodule

@ -0,0 +1 @@
Subproject commit f197cdb935b0cfd9881fdc6860874cb8379d1238

View file

@ -0,0 +1,209 @@
#include "amnezia_application.h"
#include <QFontDatabase>
#include <QTimer>
#include <QTranslator>
#include "QZXing.h"
#include "core/servercontroller.h"
#include "debug.h"
#include "defines.h"
#include "platforms/ios/QRCodeReaderBase.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"
#if defined(Q_OS_IOS)
#include "platforms/ios/QtAppDelegate-C-Interface.h"
#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<Settings>(new Settings);
m_serverController = std::shared_ptr<ServerController>(new ServerController(m_settings, this));
m_configurator = std::shared_ptr<VpnConfigurator>(new VpnConfigurator(m_settings, m_serverController, this));
}
AmneziaApplication::~AmneziaApplication()
{
QObject::disconnect(m_engine, 0,0,0);
delete m_engine;
QObject::disconnect(m_uiLogic, 0,0,0);
delete m_uiLogic;
delete m_protocolProps;
delete m_containerProps;
}
void AmneziaApplication::init()
{
m_engine = new QQmlApplicationEngine;
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,
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(m_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
m_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>("VpnProtocol::VpnConnectionState");
qRegisterMetaType<ServerCredentials>("ServerCredentials");
qRegisterMetaType<DockerContainer>("DockerContainer");
qRegisterMetaType<TransportProto>("TransportProto");
qRegisterMetaType<Proto>("Proto");
qRegisterMetaType<ServiceType>("ServiceType");
qRegisterMetaType<Page>("Page");
qRegisterMetaType<VpnProtocol::VpnConnectionState>("ConnectionState");
qRegisterMetaType<PageProtocolLogicBase *>("PageProtocolLogicBase *");
declareQmlPageEnum();
declareQmlProtocolEnum();
declareQmlContainerEnum();
qmlRegisterType<PageType>("PageType", 1, 0, "PageType");
qmlRegisterType<QRCodeReader>("QRCodeReader", 1, 0, "QRCodeReader");
m_containerProps = new ContainerProps;
qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", m_containerProps);
m_protocolProps = new ProtocolProps;
qmlRegisterSingletonInstance("ProtocolProps", 1, 0, "ProtocolProps", m_protocolProps);
}
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();
}
}

View file

@ -0,0 +1,57 @@
#ifndef AMNEZIA_APPLICATION_H
#define AMNEZIA_APPLICATION_H
#include <QApplication>
#include <QGuiApplication>
#include <QCommandLineParser>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#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 QApplication
#else
#define AMNEZIA_BASE_CLASS SingleApplication
#define QAPPLICATION_CLASS QApplication
#include "singleapplication.h"
#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<Settings> m_settings;
std::shared_ptr<VpnConfigurator> m_configurator;
std::shared_ptr<ServerController> m_serverController;
ContainerProps* m_containerProps;
ProtocolProps* m_protocolProps;
QTranslator* m_translator;
QCommandLineParser m_parser;
};
#endif // AMNEZIA_APPLICATION_H

View file

@ -48,7 +48,7 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.0.10"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
implementation project(path: ':shadowsocks')
}
@ -97,6 +97,9 @@ android {
}
compileOptions {
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

View file

@ -520,7 +520,9 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
peerBuilder.addAllowedIp(network)
}
}
peerBuilder.setEndpoint(InetEndpoint.parse(peerConfig["Endpoint"]))
val endpointConfig = peerConfig["Endpoint"]
val endpoint = InetEndpoint.parse(endpointConfig)
peerBuilder.setEndpoint(endpoint)
peerConfig["PersistentKeepalive"]?.let {
peerBuilder.setPersistentKeepalive(it.toInt())
}

View file

@ -2,7 +2,6 @@ QT += widgets core gui network xml remoteobjects quick svg
TARGET = AmneziaVPN
TEMPLATE = app
#CONFIG += console
CONFIG += qtquickcompiler
CONFIG += qzxing_multimedia \
@ -16,31 +15,37 @@ 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")
include("3rd/qtkeychain/qtkeychain.pri")
INCLUDEPATH += $$PWD/3rd/QSimpleCrypto/include
INCLUDEPATH += $$PWD/3rd/OpenSSL/include
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/configurator_base.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 \
ui/models/containers_model.h \
@ -49,10 +54,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 \
@ -61,16 +66,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 \
@ -81,24 +86,27 @@ 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/configurator_base.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 \
ui/models/containers_model.cpp \
@ -106,10 +114,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 \
@ -118,15 +126,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 \
@ -165,7 +173,6 @@ win32 {
-lshlwapi \
-liphlpapi \
-lws2_32 \
-liphlpapi \
-lgdi32
@ -246,20 +253,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/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_PACKAGE_SOURCE_DIR = $$PWD/android
for (abi, ANDROID_ABIS): {
equals(ANDROID_TARGET_ARCH,$$abi) {
@ -280,7 +287,7 @@ android {
}
ios {
message("Client ios build")
message("Client iOS build")
CONFIG += static
CONFIG += file_copies
@ -307,7 +314,7 @@ ios {
platforms/ios/QtAppDelegate-C-Interface.h
SOURCES -= \
platforms/ios/QRCodeReader.cpp \
platforms/ios/QRCodeReaderBase.cpp \
platforms/ios/MobileUtils.cpp
SOURCES += \

View file

@ -4,18 +4,25 @@
#include <QJsonObject>
#include <QJsonDocument>
#include "core/servercontroller.h"
#include "containers/containers_defs.h"
CloakConfigurator::CloakConfigurator(std::shared_ptr<Settings> settings, std::shared_ptr<ServerController> 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;

View file

@ -3,15 +3,18 @@
#include <QObject>
#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> settings,
std::shared_ptr<ServerController> 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);
};

View file

@ -0,0 +1,10 @@
#include "configurator_base.h"
ConfiguratorBase::ConfiguratorBase(std::shared_ptr<Settings> settings,
std::shared_ptr<ServerController> serverController, QObject *parent)
: QObject{parent},
m_settings(settings),
m_serverController(serverController)
{
}

View file

@ -0,0 +1,25 @@
#ifndef CONFIGURATORBASE_H
#define CONFIGURATORBASE_H
#include <QObject>
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> settings,
std::shared_ptr<ServerController> serverController, QObject *parent = nullptr);
protected:
std::shared_ptr<Settings> m_settings;
std::shared_ptr<ServerController> m_serverController;
};
#endif // CONFIGURATORBASE_H

View file

@ -8,13 +8,18 @@
#include <QJsonDocument>
#include <QUuid>
#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> settings, std::shared_ptr<ServerController> 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();

View file

@ -4,12 +4,15 @@
#include <QObject>
#include <QProcessEnvironment>
#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> settings,
std::shared_ptr<ServerController> serverController, QObject *parent = nullptr);
struct ConnectionData {
QByteArray clientCert; // p12 client cert
@ -19,14 +22,14 @@ public:
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);
};

View file

@ -6,16 +6,25 @@
#include <QDebug>
#include <QTemporaryFile>
#include <QJsonObject>
#include <QJsonDocument>
#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 <openssl/rsa.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
OpenVpnConfigurator::OpenVpnConfigurator(std::shared_ptr<Settings> settings, std::shared_ptr<ServerController> 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()

View file

@ -4,13 +4,15 @@
#include <QObject>
#include <QProcessEnvironment>
#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> settings,
std::shared_ptr<ServerController> serverController, QObject *parent = nullptr);
struct ConnectionData {
QString clientId;
@ -22,22 +24,21 @@ public:
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

View file

@ -5,13 +5,20 @@
#include <QJsonDocument>
#include "containers/containers_defs.h"
#include "core/servercontroller.h"
ShadowSocksConfigurator::ShadowSocksConfigurator(std::shared_ptr<Settings> settings, std::shared_ptr<ServerController> 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;

View file

@ -3,15 +3,17 @@
#include <QObject>
#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> settings,
std::shared_ptr<ServerController> 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);
};

View file

@ -14,8 +14,15 @@
#include "core/server_defs.h"
#include "utils.h"
#include "sftpdefs.h"
using namespace QSsh;
SshConfigurator::SshConfigurator(std::shared_ptr<Settings> settings, std::shared_ptr<ServerController> serverController, QObject *parent):
ConfiguratorBase(settings, serverController, parent)
{
}
QString SshConfigurator::convertOpenSShKey(const QString &key)
{

View file

@ -4,16 +4,19 @@
#include <QObject>
#include <QProcessEnvironment>
#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> settings,
std::shared_ptr<ServerController> serverController, QObject *parent = nullptr);
QProcessEnvironment prepareEnv();
QString convertOpenSShKey(const QString &key);
void openSshTerminal(const ServerCredentials &credentials);
};

View file

@ -4,18 +4,26 @@
#include "shadowsocks_configurator.h"
#include "wireguard_configurator.h"
#include "ikev2_configurator.h"
#include "ssh_configurator.h"
#include <QFile>
#include <QJsonObject>
#include <QJsonDocument>
#include "containers/containers_defs.h"
#include "settings.h"
#include "utils.h"
Settings &VpnConfigurator::m_settings()
VpnConfigurator::VpnConfigurator(std::shared_ptr<Settings> settings,
std::shared_ptr<ServerController> serverController, QObject *parent):
ConfiguratorBase(settings, serverController, parent)
{
static Settings s;
return s;
openVpnConfigurator = std::shared_ptr<OpenVpnConfigurator>(new OpenVpnConfigurator(settings, serverController, this));
shadowSocksConfigurator = std::shared_ptr<ShadowSocksConfigurator>(new ShadowSocksConfigurator(settings, serverController, this));
cloakConfigurator = std::shared_ptr<CloakConfigurator>(new CloakConfigurator(settings, serverController, this));
wireguardConfigurator = std::shared_ptr<WireguardConfigurator>(new WireguardConfigurator(settings, serverController, this));
ikev2Configurator = std::shared_ptr<Ikev2Configurator>(new Ikev2Configurator(settings, serverController, this));
sshConfigurator = std::shared_ptr<SshConfigurator>(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<QString, QString> VpnConfigurator::getDnsForConfig(int serverIndex)
{
QPair<QString, QString> 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;
}

View file

@ -3,29 +3,46 @@
#include <QObject>
#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> settings,
std::shared_ptr<ServerController> 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<QString, QString> getDnsForConfig(int serverIndex);
static QString &processConfigWithDnsSettings(int serverIndex, DockerContainer container, Proto proto, QString &config);
QPair<QString, QString> 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<ServerController> m_serverController;
std::shared_ptr<OpenVpnConfigurator> openVpnConfigurator;
std::shared_ptr<ShadowSocksConfigurator> shadowSocksConfigurator;
std::shared_ptr<CloakConfigurator> cloakConfigurator;
std::shared_ptr<WireguardConfigurator> wireguardConfigurator;
std::shared_ptr<Ikev2Configurator> ikev2Configurator;
std::shared_ptr<SshConfigurator> sshConfigurator;
};
#endif // VPN_CONFIGURATOR_H

View file

@ -5,19 +5,28 @@
#include <QTemporaryDir>
#include <QDebug>
#include <QTemporaryFile>
#include <QJsonDocument>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#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> settings, std::shared_ptr<ServerController> 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;
}

View file

@ -4,13 +4,15 @@
#include <QObject>
#include <QProcessEnvironment>
#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> settings,
std::shared_ptr<ServerController> serverController, QObject *parent = nullptr);
struct ConnectionData {
QString clientPrivKey; // client private key
@ -21,20 +23,18 @@ public:
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

View file

@ -46,7 +46,6 @@ enum ErrorCode
FailedToSaveConfigData,
OpenVpnConfigMissing,
OpenVpnManagementServerError,
EasyRsaError,
ConfigMissing,
// Distro errors

View file

@ -35,10 +35,11 @@ QString errorString(ErrorCode code){
case (FailedToSaveConfigData): return QObject::tr("Failed to save config to disk");
case (OpenVpnConfigMissing): return QObject::tr("OpenVPN config missing");
case (OpenVpnManagementServerError): return QObject::tr("OpenVPN management server error");
case (EasyRsaError): return QObject::tr("EasyRSA runtime error");
// Distro errors
case (OpenVpnExecutableMissing): return QObject::tr("OpenVPN executable missing");
case (ShadowSocksExecutableMissing): return QObject::tr("ShadowSocks (ss-local) executable missing");
case (CloakExecutableMissing): return QObject::tr("Cloak (ck-client) executable missing");
case (AmneziaServiceConnectionFailed): return QObject::tr("Amnezia helper service error");
case (OpenSslFailed): return QObject::tr("OpenSSL failed");

View file

@ -18,18 +18,18 @@
#include "containers/containers_defs.h"
#include "server_defs.h"
#include "settings.h"
#include "scripts_registry.h"
#include "utils.h"
#include <configurators/vpn_configurator.h>
using namespace QSsh;
Settings &ServerController::m_settings()
ServerController::ServerController(std::shared_ptr<Settings> 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

View file

@ -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> settings, QObject *parent = nullptr);
typedef QList<QPair<QString, QString>> 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<void(const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &cbReadStdOut = nullptr,
const std::function<void(const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &cbReadStdErr = nullptr);
static ErrorCode runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script,
ErrorCode runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script,
const std::function<void(const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &cbReadStdOut = nullptr,
const std::function<void(const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &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<Settings> m_settings;
std::shared_ptr<VpnConfigurator> m_configurator;
};
#endif // SERVERCONTROLLER_H

View file

@ -1,54 +1,10 @@
#include <QApplication>
#include <QFontDatabase>
#include <QCommandLineParser>
#include <QMessageBox>
#include <QTranslator>
#include <QTimer>
#include <QLoggingCategory>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "ui/uilogic.h"
#include <QDebug>
#include <QTimer>
#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 "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"
#endif
@ -58,29 +14,24 @@
#endif
#if defined(Q_OS_IOS)
#include "QtAppDelegate-C-Interface.h"
#include "platforms/ios/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, [&](){
@ -88,10 +39,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
@ -104,147 +54,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();
app.loadTranslator();
app.loadFonts();
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 settings;
if (settings.isSaveLogs()) {
if (!Debug::init()) {
qWarning() << "Initialization of debug subsystem failed";
}
}
app.setQuitOnLastWindowClosed(false);
QZXing::registerQMLTypes();
qRegisterMetaType<VpnProtocol::VpnConnectionState>("VpnProtocol::VpnConnectionState");
qRegisterMetaType<ServerCredentials>("ServerCredentials");
qRegisterMetaType<DockerContainer>("DockerContainer");
qRegisterMetaType<TransportProto>("TransportProto");
qRegisterMetaType<Proto>("Proto");
qRegisterMetaType<ServiceType>("ServiceType");
qRegisterMetaType<Page>("Page");
qRegisterMetaType<VpnProtocol::VpnConnectionState>("ConnectionState");
qRegisterMetaType<PageProtocolLogicBase *>("PageProtocolLogicBase *");
UiLogic *uiLogic = new UiLogic;
QQmlApplicationEngine *engine = new QQmlApplicationEngine;
declareQmlPageEnum();
declareQmlProtocolEnum();
declareQmlContainerEnum();
qmlRegisterType<PageType>("PageType", 1, 0, "PageType");
qmlRegisterType<QRCodeReader>("QRCodeReader", 1, 0, "QRCodeReader");
QScopedPointer<ContainerProps> containerProps(new ContainerProps);
qmlRegisterSingletonInstance("ContainerProps", 1, 0, "ContainerProps", containerProps.get());
QScopedPointer<ProtocolProps> 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());
#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();
}

View file

@ -1,5 +1,5 @@
#include "MobileUtils.h"
void MobileUtils::shareText(const QStringList& filesToSend) {
void MobileUtils::shareText(const QStringList&) {}
}

View file

@ -12,6 +12,7 @@ public:
public slots:
static void shareText(const QStringList& filesToSend);
};
#endif // MOBILEUTILS_H

View file

@ -1,6 +1,9 @@
#include "MobileUtils.h"
#include <UIKit/UIKit.h>
#include <Security/Security.h>
#include <QDebug>
static UIViewController* getViewController() {
NSArray *windows = [[UIApplication sharedApplication]windows];
@ -31,3 +34,4 @@ void MobileUtils::shareText(const QStringList& filesToSend) {
popController.sourceView = qtController.view;
}
}

View file

@ -1,5 +1,4 @@
#include "openvpnovercloakprotocol.h"
#include "core/servercontroller.h"
#include "utils.h"
#include "containers/containers_defs.h"
@ -27,6 +26,10 @@ OpenVpnOverCloakProtocol::~OpenVpnOverCloakProtocol()
ErrorCode OpenVpnOverCloakProtocol::start()
{
if (!QFileInfo::exists(cloakExecPath())) {
setLastError(ErrorCode::CloakExecutableMissing);
return lastError();
}
#ifndef Q_OS_IOS
if (Utils::processIsRunning(Utils::executable("ck-client", false))) {
Utils::killProcessByName(Utils::executable("ck-client", false));
@ -106,6 +109,8 @@ QString OpenVpnOverCloakProtocol::cloakExecPath()
{
#ifdef Q_OS_WIN
return Utils::executable(QString("cloak/ck-client"), true);
#elif defined Q_OS_LINUX
return Utils::usrExecutable("ck-client");
#else
return Utils::executable(QString("/ck-client"), true);
#endif

View file

@ -1,5 +1,4 @@
#include "shadowsocksvpnprotocol.h"
#include "core/servercontroller.h"
#include "debug.h"
#include "utils.h"
@ -27,6 +26,13 @@ ShadowSocksVpnProtocol::~ShadowSocksVpnProtocol()
ErrorCode ShadowSocksVpnProtocol::start()
{
if (!QFileInfo::exists(shadowSocksExecPath())) {
setLastError(ErrorCode::ShadowSocksExecutableMissing);
return lastError();
}
#ifndef Q_OS_IOS
if (Utils::processIsRunning(Utils::executable("ss-local", false))) {
Utils::killProcessByName(Utils::executable("ss-local", false));

View file

@ -270,6 +270,6 @@ print G "done."
sed -i '' '/<string>Original<\/string>/d' AmneziaVPN.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
fi
print Y "Opening in XCode..."
open AmneziaVPN.xcodeproj
# print Y "Opening in XCode..."
# open AmneziaVPN.xcodeproj
print G "All done!"

254
client/secure_qsettings.cpp Normal file
View file

@ -0,0 +1,254 @@
#include "secure_qsettings.h"
#include "platforms/ios/MobileUtils.h"
#include <QDataStream>
#include <QDebug>
#include <QEventLoop>
#include <QJsonDocument>
#include <QJsonObject>
#include <QTimer>
#include "utils.h"
#include <QRandomGenerator>
#include "QAead.h"
#include "QBlockCipher.h"
using namespace QKeychain;
SecureQSettings::SecureQSettings(const QString &organization, const QString &application, QObject *parent)
: QObject{parent},
m_settings(organization, application, parent),
encryptedKeys({"Servers/serversList"})
{
bool encrypted = m_settings.value("Conf/encrypted").toBool();
// convert settings to encrypted for if updated to >= 2.1.0
if (encryptionRequired() && ! encrypted) {
for (const QString &key : m_settings.allKeys()) {
if (encryptedKeys.contains(key)) {
const QVariant &val = value(key);
setValue(key, val);
}
}
m_settings.setValue("Conf/encrypted", true);
m_settings.sync();
}
}
QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue) const
{
QMutexLocker locker(&mutex);
if (m_cache.contains(key)) {
return m_cache.value(key);
}
if (!m_settings.contains(key)) return defaultValue;
QVariant retVal;
// 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 (getEncKey().isEmpty() || getEncIv().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);
ds >> retVal;
if (!retVal.isValid()) {
qWarning() << "SecureQSettings::value settings decryption failed";
retVal = QVariant();
}
}
}
else {
qWarning() << "SecureQSettings::value invalid QVariant value";
retVal = QVariant();
}
m_cache.insert(key, retVal);
return retVal;
}
void SecureQSettings::setValue(const QString &key, const QVariant &value)
{
QMutexLocker locker(&mutex);
if (encryptionRequired() && encryptedKeys.contains(key)) {
if (!getEncKey().isEmpty() && !getEncIv().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;
}
}
else {
m_settings.setValue(key, value);
}
m_cache.insert(key, value);
sync();
}
void SecureQSettings::remove(const QString &key)
{
QMutexLocker locker(&mutex);
m_settings.remove(key);
m_cache.remove(key);
sync();
}
void SecureQSettings::sync()
{
m_settings.sync();
}
QByteArray SecureQSettings::backupAppConfig() const
{
QJsonObject cfg;
for (const QString &key : m_settings.allKeys()) {
cfg.insert(key, QJsonValue::fromVariant(value(key)));
}
return QJsonDocument(cfg).toJson();
}
bool SecureQSettings::restoreAppConfig(const QByteArray &json)
{
QJsonObject cfg = QJsonDocument::fromJson(json).object();
if (cfg.isEmpty()) return false;
for (const QString &key : cfg.keys()) {
setValue(key, cfg.value(key).toVariant());
}
sync();
return true;
}
QByteArray SecureQSettings::encryptText(const QByteArray& value) const
{
QSimpleCrypto::QBlockCipher cipher;
return cipher.encryptAesBlockCipher(value, getEncKey(), getEncIv());
}
QByteArray SecureQSettings::decryptText(const QByteArray& ba) const
{
QSimpleCrypto::QBlockCipher cipher;
return cipher.decryptAesBlockCipher(ba, getEncKey(), getEncIv());
}
bool SecureQSettings::encryptionRequired() const
{
// TODO: review on linux
return true;
}
QByteArray SecureQSettings::getEncKey() const
{
// load keys from system key storage
m_key = getSecTag(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";
}
setSecTag(settingsKeyTag, key);
// check
m_key = getSecTag(settingsKeyTag);
if (key != m_key) {
qCritical() << "SecureQSettings::getEncKey Unable to store key in keychain" << key.size() << m_key.size();
return {};
}
}
return m_key;
}
QByteArray SecureQSettings::getEncIv() const
{
// load keys from system key storage
m_iv = getSecTag(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";
}
setSecTag(settingsIvTag, iv);
// check
m_iv = getSecTag(settingsIvTag);
if (iv != m_iv) {
qCritical() << "SecureQSettings::getEncIv Unable to store IV in keychain" << iv.size() << m_iv.size();
return {};
}
}
return m_iv;
}
QByteArray SecureQSettings::getSecTag(const QString &tag)
{
ReadPasswordJob job("get-" + tag);
job.setAutoDelete(false);
job.setKey(tag);
QEventLoop loop;
job.connect(&job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()));
job.start();
loop.exec();
if ( job.error() ) {
qCritical() << "SecureQSettings::getSecTag Error:" << job.errorString();
}
return job.binaryData();
}
void SecureQSettings::setSecTag(const QString &tag, const QByteArray &data)
{
WritePasswordJob job("set-" + tag);
job.setAutoDelete(false);
job.setKey(tag);
job.setBinaryData(data);
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
job.connect(&job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()));
job.start();
loop.exec();
if (job.error()) {
qCritical() << "SecureQSettings::setSecTag Error:" << job.errorString();
}
}

55
client/secure_qsettings.h Normal file
View file

@ -0,0 +1,55 @@
#ifndef SECUREQSETTINGS_H
#define SECUREQSETTINGS_H
#include <QSettings>
#include <QObject>
#include <QMutex>
#include <QMutexLocker>
#include "keychain.h"
constexpr const char* settingsKeyTag = "settingsKeyTag";
constexpr const char* settingsIvTag = "settingsIvTag";
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 remove(const QString &key);
void sync();
QByteArray backupAppConfig() const;
bool restoreAppConfig(const QByteArray &json);
QByteArray encryptText(const QByteArray &value) const;
QByteArray decryptText(const QByteArray& ba) const;
bool encryptionRequired() const;
QByteArray getEncKey() const;
QByteArray getEncIv() const;
static QByteArray getSecTag(const QString &tag);
static void setSecTag(const QString &tag, const QByteArray &data);
private:
QSettings m_settings;
mutable QMap<QString, QVariant> m_cache;
QStringList encryptedKeys; // encode only key listed here
mutable QByteArray m_key;
mutable QByteArray m_iv;
const QByteArray magicString { "EncData" }; // Magic keyword used for mark encrypted QByteArray
mutable QMutex mutex;
};
#endif // SECUREQSETTINGS_H

View file

@ -2,15 +2,15 @@
#include "settings.h"
#include "utils.h"
#include <QDebug>
#include "containers/containers_defs.h"
const char Settings::cloudFlareNs1[] = "1.1.1.1";
const char Settings::cloudFlareNs2[] = "1.0.0.1";
Settings::Settings(QObject* parent) :
QObject(parent),
m_settings (ORGANIZATION_NAME, APPLICATION_NAME, this)
m_settings(ORGANIZATION_NAME, APPLICATION_NAME, this)
{
// Import old settings
if (serversCount() == 0) {
@ -178,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
@ -292,60 +291,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());

View file

@ -11,6 +11,7 @@
#include "core/defs.h"
#include "containers/containers_defs.h"
#include "secure_qsettings.h"
using namespace amnezia;
@ -25,7 +26,6 @@ public:
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()); }
@ -110,13 +110,11 @@ public:
// static constexpr char openNicNs5[] = "94.103.153.176";
// static constexpr char openNicNs13[] = "144.76.103.143";
public:
QByteArray backupAppConfig() const { return m_settings.backupAppConfig(); }
bool restoreAppConfig(const QByteArray &cfg) { return m_settings.restoreAppConfig(cfg); }
private:
QSettings m_settings;
SecureQSettings m_settings;
};

View file

@ -1,6 +1,7 @@
#include "containers_model.h"
ContainersModel::ContainersModel(QObject *parent) :
ContainersModel::ContainersModel(std::shared_ptr<Settings> 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();
}

View file

@ -13,7 +13,7 @@ class ContainersModel : public QAbstractListModel
{
Q_OBJECT
public:
ContainersModel(QObject *parent = nullptr);
ContainersModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
public:
enum SiteRoles {
NameRole = Qt::UserRole + 1,
@ -33,7 +33,7 @@ protected:
private:
int m_selectedServerIndex;
Settings m_settings;
std::shared_ptr<Settings> m_settings;
};
#endif // CONTAINERS_MODEL_H

View file

@ -1,6 +1,7 @@
#include "protocols_model.h"
ProtocolsModel::ProtocolsModel(QObject *parent) :
ProtocolsModel::ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent) :
m_settings(settings),
QAbstractListModel(parent)
{

View file

@ -13,7 +13,7 @@ class ProtocolsModel : public QAbstractListModel
{
Q_OBJECT
public:
ProtocolsModel(QObject *parent = nullptr);
ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
public:
enum SiteRoles {
NameRole = Qt::UserRole + 1,
@ -34,7 +34,7 @@ protected:
private:
int m_selectedServerIndex;
DockerContainer m_selectedDockerContainer;
Settings m_settings;
std::shared_ptr<Settings> m_settings;
};
#endif // PROTOCOLS_MODEL_H

View file

@ -1,7 +1,8 @@
#include "sites_model.h"
SitesModel::SitesModel(Settings::RouteMode mode, QObject *parent)
SitesModel::SitesModel(std::shared_ptr<Settings> 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()));

View file

@ -15,7 +15,7 @@ public:
IpRole
};
explicit SitesModel(Settings::RouteMode mode, QObject *parent = nullptr);
explicit SitesModel(std::shared_ptr<Settings> settings, Settings::RouteMode mode, QObject *parent = nullptr);
void resetCache();
// Basic functionality:
@ -32,7 +32,7 @@ private:
private:
Settings::RouteMode m_mode;
Settings m_settings;
std::shared_ptr<Settings> m_settings;
mutable QVector<QPair<QString, QString>> m_ipsCache;
mutable bool m_cacheReady = false;

View file

@ -7,6 +7,7 @@
#include <QDesktopServices>
#include <QFileDialog>
#include <QMessageBox>
#include <QStandardPaths>
using namespace amnezia;
@ -25,9 +26,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 +47,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()
@ -74,3 +75,32 @@ 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();
bool ok = m_settings->restoreAppConfig(data);
if (ok) {
emit uiLogic()->goToPage(Page::Vpn);
emit uiLogic()->setStartPage(Page::Vpn);
}
else {
QMessageBox::warning(nullptr, APPLICATION_NAME,
tr("Can't import config, file is corrupted."));
}
}

View file

@ -25,6 +25,10 @@ public:
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;

View file

@ -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<ProtocolsModel *>(uiLogic()->protocolsModel())->setSelectedServerIndex(uiLogic()->selectedServerIndex);
qobject_cast<ProtocolsModel *>(uiLogic()->protocolsModel())->setSelectedDockerContainer(uiLogic()->selectedDockerContainer);

View file

@ -1,6 +1,7 @@
#include "NetworkSettingsLogic.h"
#include "defines.h"
#include "settings.h"
#include "utils.h"
NetworkSettingsLogic::NetworkSettingsLogic(UiLogic *logic, QObject *parent):
@ -13,39 +14,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);
}

View file

@ -2,6 +2,7 @@
#define NEW_SERVER_PROTOCOLS_LOGIC_H
#include "PageLogicBase.h"
#include "containers/containers_defs.h"
class UiLogic;

View file

@ -1,11 +1,17 @@
#include "PageLogicBase.h"
#include "ui/uilogic.h"
#include "settings.h"
#include "configurators/vpn_configurator.h"
PageLogicBase::PageLogicBase(UiLogic *logic, QObject *parent):
QObject(parent),
m_pageEnabled{true},
m_uiLogic(logic)
{
m_settings = logic->m_settings;
m_configurator = logic->m_configurator;
m_serverController = logic->m_serverController;
}

View file

@ -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 @@ public:
Q_INVOKABLE virtual void onUpdatePage() {}
protected:
UiLogic *m_uiLogic;
UiLogic *uiLogic() const { return m_uiLogic; }
Settings m_settings;
UiLogic *m_uiLogic;
std::shared_ptr<Settings> m_settings;
std::shared_ptr<VpnConfigurator> m_configurator;
std::shared_ptr<ServerController> m_serverController;
signals:
void updatePage();

View file

@ -3,6 +3,9 @@
#include <functional>
#include "PageLogicBase.h"
#include "core/defs.h"
using namespace amnezia;
class UiLogic;

View file

@ -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,33 +67,33 @@ 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 = m_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();
}
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) {
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);
}
}

View file

@ -2,6 +2,7 @@
#define SERVER_CONTAINERS_LOGIC_H
#include "PageLogicBase.h"
#include "containers/containers_defs.h"
class UiLogic;

View file

@ -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<ServerModelContent> serverListContent;
for(int i = 0; i < servers.size(); i++) {
ServerModelContent c;

View file

@ -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,14 +48,14 @@ 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 = 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."));
@ -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();
}

View file

@ -21,6 +21,7 @@
#include "defines.h"
#include "core/defs.h"
#include "core/errorstrings.h"
#include "core/servercontroller.h"
#include <functional>
#include "../uilogic.h"
@ -73,19 +74,19 @@ 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);
QString cfg = m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, p, &e);
if (e) {
cfg = "Error generating config";
break;
@ -96,14 +97,14 @@ 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);
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);
@ -129,13 +130,13 @@ 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);
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());
}
@ -144,16 +145,16 @@ 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);
cfg = m_configurator->shadowSocksConfigurator->genShadowSocksConfig(credentials, container, containerConfig, &e);
}
QJsonObject ssConfig = QJsonDocument::fromJson(cfg.toUtf8()).object();
@ -186,16 +187,16 @@ 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);
cfg = m_configurator->cloakConfigurator->genCloakConfig(credentials, container, containerConfig, &e);
}
QJsonObject cloakConfig = QJsonDocument::fromJson(cfg.toUtf8()).object();
@ -209,19 +210,19 @@ 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);
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);
@ -235,22 +236,20 @@ 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);
Ikev2Configurator::ConnectionData connData = m_configurator->ikev2Configurator->prepareIkev2Config(credentials, container);
Ikev2Configurator::ConnectionData connData = 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);
}

View file

@ -2,6 +2,7 @@
#define SHARE_CONNECTION_LOGIC_H
#include "PageLogicBase.h"
#include "containers/containers_defs.h"
class UiLogic;

View file

@ -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<SitesModel*> (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<QString, QString> 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()) {

View file

@ -2,6 +2,7 @@
#define SITES_LOGIC_H
#include "PageLogicBase.h"
#include "settings.h"
class UiLogic;
class SitesModel;

View file

@ -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"
@ -24,7 +25,6 @@ StartPageLogic::StartPageLogic(UiLogic *logic, QObject *parent):
m_labelWaitInfoVisible{true},
m_labelWaitInfoText{},
m_pushButtonBackFromStartVisible{true},
m_pushButtonConnectVisible{true},
m_ipAddressPortRegex{Utils::ipAddressPortRegExp()}
{
@ -41,7 +41,6 @@ void StartPageLogic::onUpdatePage()
set_labelWaitInfoVisible(false);
set_labelWaitInfoText("");
set_pushButtonConnectVisible(true);
set_pushButtonConnectKeyChecked(false);
@ -50,8 +49,6 @@ void StartPageLogic::onUpdatePage()
void StartPageLogic::onPushButtonConnect()
{
// uiLogic()->goToPage(Page::NewServer);
// return;
if (pushButtonConnectKeyChecked()){
if (lineEditIpText().isEmpty() ||
lineEditLoginText().isEmpty() ||
@ -68,7 +65,6 @@ void StartPageLogic::onPushButtonConnect()
return;
}
}
qDebug() << "UiLogic::onPushButtonConnect checking new server";
ServerCredentials serverCredentials;
serverCredentials.hostName = lineEditIpText();
@ -85,7 +81,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;
@ -99,7 +95,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
@ -153,16 +149,9 @@ 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);
m_settings->addServer(profile);
m_settings->setDefaultServer(m_settings->serversCount() - 1);
emit uiLogic()->goToPage(Page::Vpn);
emit uiLogic()->setStartPage(Page::Vpn);
@ -174,8 +163,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);
@ -209,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);

View file

@ -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:

View file

@ -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 = m_configurator->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);
}
@ -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()

View file

@ -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);
}
}

View file

@ -2,6 +2,7 @@
#define WIZARD_LOGIC_H
#include "PageLogicBase.h"
#include "containers/containers_defs.h"
class UiLogic;

View file

@ -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 m_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;

View file

@ -32,7 +32,6 @@ public:
QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
private:
Settings m_settings;
UiLogic *m_uiLogic;
};

View file

@ -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 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);
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;
}

View file

@ -44,7 +44,6 @@ public:
QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
private:
Settings m_settings;
UiLogic *m_uiLogic;
};

View file

@ -5,7 +5,6 @@
#include <QStandardPaths>
#include "OtherProtocolsLogic.h"
#include "core/servercontroller.h"
#include <functional>
#include "../../uilogic.h"
#include "utils.h"
@ -82,7 +81,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

View file

@ -31,7 +31,6 @@ public:
//QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
private:
Settings m_settings;
UiLogic *m_uiLogic;
#ifdef AMNEZIA_DESKTOP

View file

@ -46,10 +46,9 @@ QJsonObject ShadowSocksLogic::getProtocolConfigFromPage(QJsonObject oldConfig)
void ShadowSocksLogic::onPushButtonSaveClicked()
{
QJsonObject protocolConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::ShadowSocks);
//protocolConfig = getShadowSocksConfigFromPage(protocolConfig);
QJsonObject protocolConfig = m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::ShadowSocks);
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 +81,14 @@ 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);
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;
}

View file

@ -30,7 +30,6 @@ public:
QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
private:
Settings m_settings;
UiLogic *m_uiLogic;
};

View file

@ -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

View file

@ -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()
}
}
}
}

View file

@ -1,462 +1,439 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.15
import SortFilterProxyModel 0.2
import ContainerProps 1.0
import ProtocolProps 1.0
import PageEnum 1.0
import ProtocolEnum 1.0
import "./"
import "../Controls"
import "../Config"
import "InstallSettings"
PageBase {
id: root
page: PageEnum.ServerContainers
logic: ServerContainersLogic
enabled: ServerContainersLogic.pageEnabled
function resetPage() {
container_selector.selectedIndex = -1
}
Connections {
target: logic
function onUpdatePage() {
root.resetPage()
}
}
BackButton {
id: back
}
Caption {
id: caption
text: container_selector.selectedIndex > 0 ? qsTr("Install new service") : qsTr("Installed services")
}
SelectContainer {
id: container_selector
onAboutToHide: {
pageLoader.focus = true
}
onContainerSelected: {
var containerProto = ContainerProps.defaultProtocol(c_index)
if (ProtocolProps.defaultPort(containerProto) < 0) {
tf_port_num.enabled = false
tf_port_num.text = qsTr("Default")
}
else tf_port_num.text = ProtocolProps.defaultPort(containerProto)
cb_port_proto.currentIndex = ProtocolProps.defaultTransportProto(containerProto)
tf_port_num.enabled = ProtocolProps.defaultPortChangeable(containerProto)
cb_port_proto.enabled = ProtocolProps.defaultTransportProtoChangeable(containerProto)
}
}
Column {
id: c1
visible: container_selector.selectedIndex > 0
width: parent.width
anchors.top: caption.bottom
anchors.topMargin: 10
Caption {
font.pixelSize: 22
text: UiLogic.containerName(container_selector.selectedIndex)
}
Text {
width: parent.width
anchors.topMargin: 10
padding: 10
font.family: "Lato"
font.styleName: "normal"
font.pixelSize: 16
color: "#181922"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
wrapMode: Text.Wrap
text: UiLogic.containerDesc(container_selector.selectedIndex)
}
}
Rectangle {
id: frame_settings
visible: container_selector.selectedIndex > 0
width: parent.width
anchors.top: c1.bottom
anchors.topMargin: 10
border.width: 1
border.color: "lightgray"
anchors.bottomMargin: 5
anchors.horizontalCenter: parent.horizontalCenter
radius: 2
Grid {
id: grid
visible: container_selector.selectedIndex > 0
anchors.fill: parent
columns: 2
horizontalItemAlignment: Grid.AlignHCenter
verticalItemAlignment: Grid.AlignVCenter
topPadding: 5
leftPadding: 10
spacing: 5
LabelType {
width: 130
text: qsTr("Port")
}
TextFieldType {
id: tf_port_num
width: parent.width - 130 - parent.spacing - parent.leftPadding * 2
}
LabelType {
width: 130
text: qsTr("Network Protocol")
}
ComboBoxType {
id: cb_port_proto
width: parent.width - 130 - parent.spacing - parent.leftPadding * 2
model: [
qsTr("udp"),
qsTr("tcp"),
]
}
}
}
BlueButtonType {
id: pb_cancel_add
visible: container_selector.selectedIndex > 0
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: pb_continue_add.top
anchors.bottomMargin: 20
width: parent.width - 40
height: 40
text: qsTr("Cancel")
font.pixelSize: 16
onClicked: container_selector.selectedIndex = -1
}
BlueButtonType {
id: pb_continue_add
visible: container_selector.selectedIndex > 0
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
width: parent.width - 40
height: 40
text: qsTr("Continue")
font.pixelSize: 16
onClicked: {
let cont = container_selector.selectedIndex
let tp = ProtocolProps.transportProtoFromString(cb_port_proto.currentText)
let port = tf_port_num.text
ServerContainersLogic.onPushButtonContinueClicked(cont, port, tp)
}
}
Flickable {
visible: container_selector.selectedIndex <= 0
clip: true
width: parent.width
anchors.top: caption.bottom
anchors.bottom: pb_add_container.top
contentHeight: col.height
Column {
visible: container_selector.selectedIndex <= 0
id: col
anchors {
left: parent.left;
right: parent.right;
}
topPadding: 20
spacing: 10
Caption {
id: cap1
text: qsTr("Installed Protocols and Services")
font.pixelSize: 20
}
SortFilterProxyModel {
id: proxyContainersModel
sourceModel: UiLogic.containersModel
filters: ValueFilter {
roleName: "is_installed_role"
value: true
}
}
SortFilterProxyModel {
id: proxyProtocolsModel
sourceModel: UiLogic.protocolsModel
filters: ValueFilter {
roleName: "is_installed_role"
value: true
}
}
ListView {
id: tb_c
x: 10
width: parent.width - 10
height: tb_c.contentItem.height
currentIndex: -1
spacing: 5
clip: true
interactive: false
model: proxyContainersModel
delegate: Item {
implicitWidth: tb_c.width - 10
implicitHeight: c_item.height
Item {
id: c_item
width: parent.width
height: row_container.height + tb_p.height
anchors.left: parent.left
Rectangle {
anchors.top: parent.top
width: parent.width
height: 1
color: "lightgray"
visible: index !== tb_c.currentIndex
}
Rectangle {
anchors.top: row_container.top
anchors.bottom: row_container.bottom
anchors.left: parent.left
anchors.right: parent.right
color: "#63B4FB"
visible: index === tb_c.currentIndex
}
RowLayout {
id: row_container
//width: parent.width
anchors.left: parent.left
anchors.right: parent.right
// anchors.top: lb_container_name.top
// anchors.bottom: lb_container_name.bottom
Text {
id: lb_container_name
text: name_role
font.pixelSize: 17
//font.bold: true
color: "#100A44"
topPadding: 5
bottomPadding: 5
leftPadding: 10
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap
Layout.fillWidth: true
MouseArea {
enabled: col.visible
anchors.top: lb_container_name.top
anchors.bottom: lb_container_name.bottom
anchors.left: parent.left
anchors.right: parent.right
propagateComposedEvents: true
onClicked: {
if (tb_c.currentIndex === index) tb_c.currentIndex = -1
else tb_c.currentIndex = index
UiLogic.protocolsModel.setSelectedDockerContainer(proxyContainersModel.mapToSource(index))
}
}
}
ImageButtonType {
id: button_remove
visible: index === tb_c.currentIndex
Layout.alignment: Qt.AlignRight
checkable: true
icon.source: "qrc:/images/delete.png"
implicitWidth: 30
implicitHeight: 30
checked: default_role
MessageDialog {
id: dialogRemove
standardButtons: StandardButton.Yes | StandardButton.Cancel
title: "AmneziaVPN"
text: qsTr("Remove container") + " " + name_role + "?" + "\n" + qsTr("This action will erase all data of this container on the server.")
onAccepted: {
tb_c.currentIndex = -1
ServerContainersLogic.onPushButtonRemoveClicked(proxyContainersModel.mapToSource(index))
}
}
onClicked: dialogRemove.open()
VisibleBehavior on visible { }
}
ImageButtonType {
id: button_share
visible: index === tb_c.currentIndex
Layout.alignment: Qt.AlignRight
icon.source: "qrc:/images/share.png"
implicitWidth: 30
implicitHeight: 30
onClicked: {
ServerContainersLogic.onPushButtonShareClicked(proxyContainersModel.mapToSource(index))
}
VisibleBehavior on visible { }
}
ImageButtonType {
id: button_default
visible: service_type_role == ProtocolEnum.Vpn
Layout.alignment: Qt.AlignRight
checkable: true
img.source: checked ? "qrc:/images/check.png" : "qrc:/images/uncheck.png"
implicitWidth: 30
implicitHeight: 30
checked: default_role
onClicked: {
ServerContainersLogic.onPushButtonDefaultClicked(proxyContainersModel.mapToSource(index))
}
}
}
ListView {
id: tb_p
currentIndex: -1
visible: index === tb_c.currentIndex
x: 10
anchors.top: row_container.bottom
width: parent.width - 40
height: visible ? tb_p.contentItem.height : 0
spacing: 0
clip: true
interactive: false
model: proxyProtocolsModel
VisibleBehavior on visible { }
delegate: Item {
id: dp_item
implicitWidth: tb_p.width - 10
implicitHeight: p_item.height
Item {
id: p_item
width: parent.width
height: lb_protocol_name.height
anchors.left: parent.left
Rectangle {
anchors.top: parent.top
width: parent.width
height: 1
color: "lightgray"
visible: index !== tb_p.currentIndex
}
// Rectangle {
// anchors.top: lb_protocol_name.top
// anchors.bottom: lb_protocol_name.bottom
// width: parent.width
// color: "#63B4FB"
// visible: index === tb_p.currentIndex
// }
// Text {
// id: lb_protocol_name
// text: name_role
// font.pixelSize: 16
// topPadding: 5
// bottomPadding: 5
// leftPadding: 10
// verticalAlignment: Text.AlignVCenter
// wrapMode: Text.WordWrap
// }
SettingButtonType {
id: lb_protocol_name
// anchors.top: lb_protocol_name.top
// anchors.bottom: lb_protocol_name.bottom
topPadding: 10
bottomPadding: 10
leftPadding: 10
anchors.left: parent.left
width: parent.width
height: 30
text: qsTr(name_role + " settings")
textItem.font.pixelSize: 16
icon.source: "qrc:/images/settings.png"
onClicked: {
tb_p.currentIndex = index
ServerContainersLogic.onPushButtonProtoSettingsClicked(
proxyContainersModel.mapToSource(tb_c.currentIndex),
proxyProtocolsModel.mapToSource(tb_p.currentIndex))
}
}
}
}
}
}
}
}
}
}
BlueButtonType {
id: pb_add_container
visible: container_selector.selectedIndex < 0
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.topMargin: 10
anchors.bottomMargin: 20
width: parent.width - 40
height: 40
text: qsTr("Install new protocols container")
font.pixelSize: 16
onClicked: container_selector.visible ? container_selector.close() : container_selector.open()
}
}
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.15
import SortFilterProxyModel 0.2
import ContainerProps 1.0
import ProtocolProps 1.0
import PageEnum 1.0
import ProtocolEnum 1.0
import "./"
import "../Controls"
import "../Config"
import "InstallSettings"
PageBase {
id: root
page: PageEnum.ServerContainers
logic: ServerContainersLogic
enabled: ServerContainersLogic.pageEnabled
function resetPage() {
container_selector.selectedIndex = -1
}
Connections {
target: logic
function onUpdatePage() {
root.resetPage()
}
}
BackButton {
id: back
}
Caption {
id: caption
text: container_selector.selectedIndex > 0 ? qsTr("Install new service") : qsTr("Installed services")
}
SelectContainer {
id: container_selector
onAboutToHide: {
pageLoader.focus = true
}
onContainerSelected: {
var containerProto = ContainerProps.defaultProtocol(c_index)
if (ProtocolProps.defaultPort(containerProto) < 0) {
tf_port_num.enabled = false
tf_port_num.text = qsTr("Default")
}
else tf_port_num.text = ProtocolProps.defaultPort(containerProto)
cb_port_proto.currentIndex = ProtocolProps.defaultTransportProto(containerProto)
tf_port_num.enabled = ProtocolProps.defaultPortChangeable(containerProto)
cb_port_proto.enabled = ProtocolProps.defaultTransportProtoChangeable(containerProto)
}
}
Column {
id: c1
visible: container_selector.selectedIndex > 0
width: parent.width
anchors.top: caption.bottom
anchors.topMargin: 10
Caption {
font.pixelSize: 22
text: UiLogic.containerName(container_selector.selectedIndex)
}
Text {
width: parent.width
anchors.topMargin: 10
padding: 10
font.family: "Lato"
font.styleName: "normal"
font.pixelSize: 16
color: "#181922"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
wrapMode: Text.Wrap
text: UiLogic.containerDesc(container_selector.selectedIndex)
}
}
Rectangle {
id: frame_settings
visible: container_selector.selectedIndex > 0
width: parent.width
anchors.top: c1.bottom
anchors.topMargin: 10
border.width: 1
border.color: "lightgray"
anchors.bottomMargin: 5
anchors.horizontalCenter: parent.horizontalCenter
radius: 2
Grid {
id: grid
visible: container_selector.selectedIndex > 0
anchors.fill: parent
columns: 2
horizontalItemAlignment: Grid.AlignHCenter
verticalItemAlignment: Grid.AlignVCenter
topPadding: 5
leftPadding: 10
spacing: 5
LabelType {
width: 130
text: qsTr("Port")
}
TextFieldType {
id: tf_port_num
width: parent.width - 130 - parent.spacing - parent.leftPadding * 2
}
LabelType {
width: 130
text: qsTr("Network Protocol")
}
ComboBoxType {
id: cb_port_proto
width: parent.width - 130 - parent.spacing - parent.leftPadding * 2
model: [
qsTr("udp"),
qsTr("tcp"),
]
}
}
}
BlueButtonType {
id: pb_cancel_add
visible: container_selector.selectedIndex > 0
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: pb_continue_add.top
anchors.bottomMargin: 20
width: parent.width - 40
height: 40
text: qsTr("Cancel")
font.pixelSize: 16
onClicked: container_selector.selectedIndex = -1
}
BlueButtonType {
id: pb_continue_add
visible: container_selector.selectedIndex > 0
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
width: parent.width - 40
height: 40
text: qsTr("Continue")
font.pixelSize: 16
onClicked: {
let cont = container_selector.selectedIndex
let tp = ProtocolProps.transportProtoFromString(cb_port_proto.currentText)
let port = tf_port_num.text
ServerContainersLogic.onPushButtonContinueClicked(cont, port, tp)
}
}
Flickable {
visible: container_selector.selectedIndex <= 0
clip: true
width: parent.width
anchors.top: caption.bottom
anchors.bottom: pb_add_container.top
contentHeight: col.height
Column {
visible: container_selector.selectedIndex <= 0
id: col
anchors {
left: parent.left;
right: parent.right;
}
topPadding: 20
spacing: 10
Caption {
id: cap1
text: qsTr("Installed Protocols and Services")
font.pixelSize: 20
}
SortFilterProxyModel {
id: proxyContainersModel
sourceModel: UiLogic.containersModel
filters: ValueFilter {
roleName: "is_installed_role"
value: true
}
}
SortFilterProxyModel {
id: proxyProtocolsModel
sourceModel: UiLogic.protocolsModel
filters: ValueFilter {
roleName: "is_installed_role"
value: true
}
}
ListView {
id: tb_c
x: 10
width: parent.width - 10
height: tb_c.contentItem.height
currentIndex: -1
spacing: 5
clip: true
interactive: false
model: proxyContainersModel
delegate: Item {
implicitWidth: tb_c.width - 10
implicitHeight: c_item.height
Item {
id: c_item
width: parent.width
height: row_container.height + tb_p.height
anchors.left: parent.left
Rectangle {
anchors.top: parent.top
width: parent.width
height: 1
color: "lightgray"
visible: index !== tb_c.currentIndex
}
Rectangle {
anchors.top: row_container.top
anchors.bottom: row_container.bottom
anchors.left: parent.left
anchors.right: parent.right
color: "#63B4FB"
visible: index === tb_c.currentIndex
}
RowLayout {
id: row_container
anchors.left: parent.left
anchors.right: parent.right
Text {
id: lb_container_name
text: name_role
font.pixelSize: 17
color: "#100A44"
topPadding: 16
bottomPadding: 12
leftPadding: 10
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap
Layout.fillWidth: true
MouseArea {
enabled: col.visible
anchors.top: lb_container_name.top
anchors.bottom: lb_container_name.bottom
anchors.left: parent.left
anchors.right: parent.right
propagateComposedEvents: true
onClicked: {
if (tb_c.currentIndex === index) tb_c.currentIndex = -1
else tb_c.currentIndex = index
UiLogic.protocolsModel.setSelectedDockerContainer(proxyContainersModel.mapToSource(index))
}
}
}
ImageButtonType {
id: button_remove
visible: index === tb_c.currentIndex
Layout.alignment: Qt.AlignRight
checkable: true
icon.source: "qrc:/images/delete.png"
implicitWidth: 30
implicitHeight: 30
checked: default_role
MessageDialog {
id: dialogRemove
standardButtons: StandardButton.Yes | StandardButton.Cancel
title: "AmneziaVPN"
text: qsTr("Remove container") + " " + name_role + "?" + "\n" + qsTr("This action will erase all data of this container on the server.")
onAccepted: {
tb_c.currentIndex = -1
ServerContainersLogic.onPushButtonRemoveClicked(proxyContainersModel.mapToSource(index))
}
}
onClicked: dialogRemove.open()
VisibleBehavior on visible { }
}
ImageButtonType {
id: button_share
visible: index === tb_c.currentIndex
Layout.alignment: Qt.AlignRight
icon.source: "qrc:/images/share.png"
implicitWidth: 30
implicitHeight: 30
onClicked: {
ServerContainersLogic.onPushButtonShareClicked(proxyContainersModel.mapToSource(index))
}
VisibleBehavior on visible { }
}
ImageButtonType {
id: button_default
visible: service_type_role == ProtocolEnum.Vpn
Layout.alignment: Qt.AlignRight
checkable: true
img.source: checked ? "qrc:/images/check.png" : "qrc:/images/uncheck.png"
implicitWidth: 30
implicitHeight: 30
checked: default_role
onClicked: {
ServerContainersLogic.onPushButtonDefaultClicked(proxyContainersModel.mapToSource(index))
}
}
}
ListView {
id: tb_p
currentIndex: -1
x: 10
anchors.top: row_container.bottom
width: parent.width - 40
height: index === tb_c.currentIndex ? tb_p.contentItem.height : 0
implicitHeight: height
spacing: 0
clip: true
interactive: false
model: proxyProtocolsModel
Behavior on height {
NumberAnimation {
duration: 200
}
}
delegate: Item {
id: dp_item
implicitWidth: tb_p.width - 10
implicitHeight: p_item.height
Item {
id: p_item
width: parent.width
height: lb_protocol_name.height
anchors.left: parent.left
Rectangle {
anchors.top: parent.top
width: parent.width
height: 1
color: "lightgray"
visible: index > 0
}
SettingButtonType {
id: lb_protocol_name
topPadding: 10
bottomPadding: 10
anchors.left: parent.left
anchors.leftMargin: 10
width: parent.width
height: 45
text: qsTr(name_role + " settings")
textItem.font.pixelSize: 16
icon.source: "qrc:/images/settings.png"
onClicked: {
tb_p.currentIndex = index
ServerContainersLogic.onPushButtonProtoSettingsClicked(
proxyContainersModel.mapToSource(tb_c.currentIndex),
proxyProtocolsModel.mapToSource(tb_p.currentIndex))
}
}
}
}
}
}
}
}
}
}
BlueButtonType {
id: pb_add_container
visible: container_selector.selectedIndex < 0
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.topMargin: 10
anchors.bottomMargin: 20
width: parent.width - 40
height: 40
text: qsTr("Install new protocols container")
font.pixelSize: 16
onClicked: container_selector.visible ? container_selector.close() : container_selector.open()
}
}

View file

@ -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()
}

View file

@ -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) {

View file

@ -74,13 +74,17 @@
using namespace amnezia;
using namespace PageEnumNS;
UiLogic::UiLogic(QObject *parent) :
UiLogic::UiLogic(std::shared_ptr<Settings> settings, std::shared_ptr<VpnConfigurator> configurator,
std::shared_ptr<ServerController> serverController,
QObject *parent) :
QObject(parent),
m_dialogConnectErrorText{}
m_settings(settings),
m_configurator(configurator),
m_serverController(serverController)
{
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, configurator, serverController);
m_vpnConnection->moveToThread(&m_vpnConnectionThread);
m_vpnConnectionThread.start();
@ -143,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);
@ -158,36 +160,23 @@ 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());
}
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()) {
if (! m_settings->isStartMinimized()) {
emit show();
}
else {
@ -235,30 +224,29 @@ 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->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()));
m_configurator->sshConfigurator->openSshTerminal(m_settings->serverCredentials(m_settings->defaultServerIndex()));
break;
case Qt::Key_Escape:
case Qt::Key_Back:
@ -280,7 +268,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 +287,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 +373,7 @@ void UiLogic::installServer(QMap<DockerContainer, QJsonObject> &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 +382,8 @@ void UiLogic::installServer(QMap<DockerContainer, QJsonObject> &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);
@ -442,9 +430,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) {
@ -587,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);
}
}
@ -632,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
@ -681,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);

View file

@ -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,18 +53,19 @@ 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(QObject *parent = nullptr);
explicit UiLogic(std::shared_ptr<Settings> settings, std::shared_ptr<VpnConfigurator> configurator,
std::shared_ptr<ServerController> serverController, QObject *parent = nullptr);
~UiLogic();
void showOnStartup();
friend class PageLogicBase;
friend class AppSettingsLogic;
friend class GeneralSettingsLogic;
friend class NetworkSettingsLogic;
@ -106,9 +110,6 @@ public:
void shareTempFile(const QString &suggestedName, QString ext, const QString& data);
QString getDialogConnectErrorText() const;
void setDialogConnectErrorText(const QString &dialogConnectErrorText);
signals:
void dialogConnectErrorTextChanged();
@ -125,9 +126,6 @@ signals:
void raise();
void toggleLogPanel();
private:
QString m_dialogConnectErrorText;
private slots:
// containers - INOUT arg
void installServer(QMap<DockerContainer, QJsonObject> &containers);
@ -212,7 +210,10 @@ private:
VpnConnection* m_vpnConnection;
QThread m_vpnConnectionThread;
Settings m_settings;
std::shared_ptr<Settings> m_settings;
std::shared_ptr<VpnConfigurator> m_configurator;
std::shared_ptr<ServerController> m_serverController;
NotificationHandler* m_notificationHandler;

View file

@ -121,7 +121,6 @@ QString Utils::getIPAddress(const QString& host)
QList<QHostAddress> 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;

View file

@ -29,9 +29,12 @@
#include "utils.h"
#include "vpnconnection.h"
VpnConnection::VpnConnection(QObject* parent) : QObject(parent),
m_settings(this)
VpnConnection::VpnConnection(std::shared_ptr<Settings> settings,
std::shared_ptr<VpnConfigurator> configurator,
std::shared_ptr<ServerController> serverController, QObject* parent) : QObject(parent),
m_settings(settings),
m_configurator(configurator),
m_serverController(serverController)
{
}
@ -56,7 +59,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 +70,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 +88,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 +107,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 +135,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 +156,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 +170,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);
}
}
@ -215,18 +218,15 @@ QString VpnConnection::createVpnConfigurationForProto(int serverIndex,
QString configData;
if (lastVpnConfig.contains(proto)) {
configData = lastVpnConfig.value(proto);
configData = VpnConfigurator::processConfigWithLocalSettings(serverIndex, container, proto, configData);
qDebug() << "VpnConnection::createVpnConfiguration: using saved config for" << ProtocolProps::protoToString(proto);
configData = m_configurator->processConfigWithLocalSettings(serverIndex, container, proto, configData);
}
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) {
@ -237,9 +237,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);
}
}
@ -272,7 +272,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;
@ -284,7 +284,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) {
@ -346,7 +346,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;
@ -360,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();
@ -382,7 +380,6 @@ void VpnConnection::disconnectFromVpn()
return;
}
m_vpnProtocol.data()->stop();
// qDebug() << "Disconnect from VPN 2";
}
VpnProtocol::VpnConnectionState VpnConnection::connectionState()

View file

@ -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(QObject* parent = nullptr);
explicit VpnConnection(std::shared_ptr<Settings> settings,
std::shared_ptr<VpnConfigurator> configurator,
std::shared_ptr<ServerController> serverController, QObject* parent = nullptr);
~VpnConnection() override;
static QString bytesPerSecToText(quint64 bytes);
@ -73,7 +78,10 @@ protected:
QSharedPointer<VpnProtocol> m_vpnProtocol;
private:
Settings m_settings;
std::shared_ptr<Settings> m_settings;
std::shared_ptr<VpnConfigurator> m_configurator;
std::shared_ptr<ServerController> m_serverController;
QJsonObject m_vpnConfiguration;
QJsonObject m_routeMode;
QString m_remoteAddress;

67
deploy/build_android.sh Normal file
View file

@ -0,0 +1,67 @@
#!/bin/bash
echo "Build script started ..."
set -o errexit -o nounset
# Hold on to current directory
PROJECT_DIR=$(pwd)
DEPLOY_DIR=$PROJECT_DIR/deploy
mkdir -p $DEPLOY_DIR/build
BUILD_DIR=$DEPLOY_DIR/build
echo "Project dir: ${PROJECT_DIR}"
echo "Build dir: ${BUILD_DIR}"
APP_NAME=AmneziaVPN
APP_FILENAME=$APP_NAME.app
APP_DOMAIN=org.amneziavpn.package
OUT_APP_DIR=$BUILD_DIR/client
BUNDLE_DIR=$OUT_APP_DIR/$APP_FILENAME
INSTALLER_DATA_DIR=$BUILD_DIR/installer/packages/$APP_DOMAIN/data
INSTALLER_BUNDLE_DIR=$BUILD_DIR/installer/$APP_FILENAME
PRO_FILE_PATH=$PROJECT_DIR/$APP_NAME.pro
QMAKE_STASH_FILE=$PROJECT_DIR/.qmake_stash
# Seacrh Qt
if [ -z "${QT_VERSION+x}" ]; then
QT_VERSION=5.15.2;
QT_BIN_DIR=$HOME/Qt/$QT_VERSION/gcc_64/bin
fi
echo "Using Qt in $QT_BIN_DIR"
# Checking env
$QT_BIN_DIR/qmake -v
make -v
gcc -v
# Build App
echo "Building App..."
cd $BUILD_DIR
$QT_BIN_DIR/qmake -r -spec android-clang CONFIG+=qtquickcompiler ANDROID_ABIS="armeabi-v7a arm64-v8a x86 x86_64" $PROJECT_DIR/AmneziaVPN.pro
$ANDROID_NDK_HOME/prebuilt/linux-x86_64/bin/make -j2
$ANDROID_NDK_HOME/prebuilt/linux-x86_64/bin/make install INSTALL_ROOT=android
# Build and run tests here
#echo "............Deploy.................."
# TODO possible solution: https://github.com/mhoeher/opentodolist/blob/b8981852e500589851132a02c5a62af9b0ed592c/ci/android-cmake-build.sh
#$QT_BIN_DIR/androiddeployqt \
# --output $OUT_APP_DIR \
# --gradle \
# --release \
# --deployment bundled
#cp $OUT_APP_DIR/build/outputs/apk/release/android-build-release-unsigned.apk \
# OpenTodoList-${ANDROID_ABIS}-${OTL_VERSION}.apk

Some files were not shown because too many files have changed in this diff Show more