Files
amnezia-client/client/ui/pages_logic/ShareConnectionLogic.cpp
T

294 lines
11 KiB
C++
Raw Normal View History

2021-09-04 11:26:16 +03:00
#include <QBuffer>
2021-11-08 15:18:52 +03:00
#include <QImage>
2021-12-20 02:29:23 +03:00
#include <QDataStream>
2021-09-03 20:17:13 +03:00
2022-09-07 09:51:03 +03:00
#include "qrcodegen.hpp"
2021-09-06 12:39:46 +03:00
#include "ShareConnectionLogic.h"
2021-09-04 11:26:16 +03:00
#include "configurators/cloak_configurator.h"
#include "configurators/vpn_configurator.h"
#include "configurators/openvpn_configurator.h"
#include "configurators/shadowsocks_configurator.h"
2021-11-15 18:17:28 +03:00
#include "configurators/wireguard_configurator.h"
#include "configurators/ikev2_configurator.h"
2021-09-04 11:26:16 +03:00
#include "configurators/ssh_configurator.h"
2021-09-03 20:17:13 +03:00
2023-05-16 07:34:06 +07:00
#include "version.h"
2021-12-20 02:29:23 +03:00
#include "core/defs.h"
2021-12-25 21:14:55 +03:00
#include "core/errorstrings.h"
2022-08-25 17:35:28 +03:00
#include "core/servercontroller.h"
2021-09-03 20:17:13 +03:00
#include <functional>
2021-09-04 11:26:16 +03:00
#include "../uilogic.h"
2021-09-03 20:17:13 +03:00
2022-03-25 12:32:36 -07:00
#ifdef __linux__
#include <math.h>
#endif
2022-09-07 09:51:03 +03:00
using namespace qrcodegen;
2021-09-07 21:01:56 +03:00
ShareConnectionLogic::ShareConnectionLogic(UiLogic *logic, QObject *parent):
PageLogicBase(logic, parent),
2021-09-08 14:23:02 +03:00
m_textEditShareOpenVpnCodeText{},
m_lineEditShareShadowSocksStringText{},
2021-11-13 16:09:08 +03:00
m_shareShadowSocksQrCodeText{},
m_textEditShareCloakText{},
2021-11-15 18:17:28 +03:00
m_textEditShareAmneziaCodeText{}
2021-09-03 20:17:13 +03:00
{
2021-09-04 11:26:16 +03:00
}
2021-11-13 16:09:08 +03:00
void ShareConnectionLogic::onUpdatePage()
2021-09-04 11:26:16 +03:00
{
2021-11-15 18:17:28 +03:00
set_textEditShareAmneziaCodeText(tr(""));
2021-12-20 02:29:23 +03:00
set_shareAmneziaQrCodeTextSeries({});
set_shareAmneziaQrCodeTextSeriesLength(0);
2021-11-15 18:17:28 +03:00
set_textEditShareOpenVpnCodeText("");
set_shareShadowSocksQrCodeText("");
set_textEditShareShadowSocksText("");
set_lineEditShareShadowSocksStringText("");
set_textEditShareCloakText("");
set_textEditShareWireGuardCodeText("");
set_shareWireGuardQrCodeText("");
set_textEditShareIkev2CertText("");
set_textEditShareIkev2MobileConfigText("");
set_textEditShareIkev2StrongSwanConfigText("");
2021-09-04 11:26:16 +03:00
}
void ShareConnectionLogic::onPushButtonShareAmneziaGenerateClicked()
{
2021-11-13 16:09:08 +03:00
set_textEditShareAmneziaCodeText("");
2021-12-20 02:29:23 +03:00
set_shareAmneziaQrCodeTextSeries({});
set_shareAmneziaQrCodeTextSeriesLength(0);
2021-11-13 17:20:23 +03:00
2021-11-13 16:09:08 +03:00
QJsonObject serverConfig;
2023-02-20 09:46:50 +03:00
int serverIndex = uiLogic()->m_selectedServerIndex;
DockerContainer container = uiLogic()->m_selectedDockerContainer;
2022-02-01 19:48:59 +03:00
2021-11-13 16:09:08 +03:00
// Full access
if (shareFullAccess()) {
2022-08-25 12:47:02 +03:00
serverConfig = m_settings->server(serverIndex);
2021-11-13 16:09:08 +03:00
}
// Container share
else {
2022-08-25 12:47:02 +03:00
ServerCredentials credentials = m_settings->serverCredentials(serverIndex);
QJsonObject containerConfig = m_settings->containerConfig(serverIndex, container);
2022-02-01 19:48:59 +03:00
containerConfig.insert(config_key::container, ContainerProps::containerToString(container));
2021-11-13 16:09:08 +03:00
ErrorCode e = ErrorCode::NoError;
2022-02-01 19:48:59 +03:00
for (Proto p: ContainerProps::protocolsForContainer(container)) {
2022-08-25 12:47:02 +03:00
QJsonObject protoConfig = m_settings->protocolConfig(serverIndex, container, p);
2021-11-13 16:09:08 +03:00
2022-08-25 17:35:28 +03:00
QString cfg = m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, p, &e);
2021-11-13 16:09:08 +03:00
if (e) {
cfg = "Error generating config";
break;
}
protoConfig.insert(config_key::last_config, cfg);
containerConfig.insert(ProtocolProps::protoToString(p), protoConfig);
2021-09-04 11:26:16 +03:00
}
2021-11-13 16:09:08 +03:00
QByteArray ba;
if (!e) {
2022-08-25 12:47:02 +03:00
serverConfig = m_settings->server(serverIndex);
2021-11-13 16:09:08 +03:00
serverConfig.remove(config_key::userName);
serverConfig.remove(config_key::password);
serverConfig.remove(config_key::port);
serverConfig.insert(config_key::containers, QJsonArray {containerConfig});
2022-02-01 19:48:59 +03:00
serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
2022-08-25 17:35:28 +03:00
auto dns = m_configurator->getDnsForConfig(serverIndex);
2022-02-01 19:48:59 +03:00
serverConfig.insert(config_key::dns1, dns.first);
serverConfig.insert(config_key::dns2, dns.second);
2021-11-13 16:09:08 +03:00
}
else {
set_textEditShareAmneziaCodeText(tr("Error while generating connection profile"));
return;
}
2021-09-04 11:26:16 +03:00
}
2021-12-20 02:29:23 +03:00
QByteArray ba = QJsonDocument(serverConfig).toJson();
2021-11-13 17:20:23 +03:00
ba = qCompress(ba, 8);
QString code = QString("vpn://%1").arg(QString(ba.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)));
2021-11-13 16:09:08 +03:00
set_textEditShareAmneziaCodeText(code);
2021-09-04 11:26:16 +03:00
2021-12-20 02:29:23 +03:00
QList<QString> qrChunks = genQrCodeImageSeries(ba);
set_shareAmneziaQrCodeTextSeries(qrChunks);
set_shareAmneziaQrCodeTextSeriesLength(qrChunks.size());
2021-09-04 11:26:16 +03:00
}
2021-09-08 14:23:02 +03:00
void ShareConnectionLogic::onPushButtonShareOpenVpnGenerateClicked()
2021-09-04 11:26:16 +03:00
{
2023-02-20 09:46:50 +03:00
int serverIndex = uiLogic()->m_selectedServerIndex;
DockerContainer container = uiLogic()->m_selectedDockerContainer;
2022-08-25 12:47:02 +03:00
ServerCredentials credentials = m_settings->serverCredentials(serverIndex);
2022-02-01 19:48:59 +03:00
2022-08-25 12:47:02 +03:00
const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container);
2021-09-04 11:26:16 +03:00
ErrorCode e = ErrorCode::NoError;
2022-08-25 17:35:28 +03:00
QString cfg = m_configurator->openVpnConfigurator->genOpenVpnConfig(credentials, container, containerConfig, &e);
cfg = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::OpenVpn, cfg);
2021-09-04 11:26:16 +03:00
2021-10-13 14:40:43 +03:00
set_textEditShareOpenVpnCodeText(QJsonDocument::fromJson(cfg.toUtf8()).object()[config_key::config].toString());
2021-11-15 18:17:28 +03:00
}
void ShareConnectionLogic::onPushButtonShareShadowSocksGenerateClicked()
{
2023-02-20 09:46:50 +03:00
int serverIndex = uiLogic()->m_selectedServerIndex;
DockerContainer container = uiLogic()->m_selectedDockerContainer;
2022-08-25 12:47:02 +03:00
ServerCredentials credentials = m_settings->serverCredentials(serverIndex);
2021-09-04 11:26:16 +03:00
2022-08-25 12:47:02 +03:00
QJsonObject protoConfig = m_settings->protocolConfig(serverIndex, container, Proto::ShadowSocks);
2021-11-15 18:17:28 +03:00
QString cfg = protoConfig.value(config_key::last_config).toString();
if (cfg.isEmpty()) {
2022-08-25 12:47:02 +03:00
const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container);
2021-11-15 18:17:28 +03:00
ErrorCode e = ErrorCode::NoError;
2022-08-25 17:35:28 +03:00
cfg = m_configurator->shadowSocksConfigurator->genShadowSocksConfig(credentials, container, containerConfig, &e);
2021-11-15 18:17:28 +03:00
}
QJsonObject ssConfig = QJsonDocument::fromJson(cfg.toUtf8()).object();
QString ssString = QString("%1:%2@%3:%4")
.arg(ssConfig.value("method").toString())
.arg(ssConfig.value("password").toString())
.arg(ssConfig.value("server").toString())
.arg(ssConfig.value("server_port").toString());
ssString = "ss://" + ssString.toUtf8().toBase64();
set_lineEditShareShadowSocksStringText(ssString);
2022-09-07 09:51:03 +03:00
QrCode qr = QrCode::encodeText(ssString.toUtf8(), QrCode::Ecc::LOW);
QString svg = QString::fromStdString(toSvgString(qr, 0));
set_shareShadowSocksQrCodeText(svgToBase64(svg));
2021-11-15 18:17:28 +03:00
QString humanString = QString("Server: %3\n"
"Port: %4\n"
"Encryption: %1\n"
"Password: %2")
.arg(ssConfig.value("method").toString())
.arg(ssConfig.value("password").toString())
.arg(ssConfig.value("server").toString())
.arg(ssConfig.value("server_port").toString());
set_textEditShareShadowSocksText(humanString);
2021-09-04 11:26:16 +03:00
}
2021-11-15 18:17:28 +03:00
void ShareConnectionLogic::onPushButtonShareCloakGenerateClicked()
2021-09-04 11:26:16 +03:00
{
2023-02-20 09:46:50 +03:00
int serverIndex = uiLogic()->m_selectedServerIndex;
DockerContainer container = uiLogic()->m_selectedDockerContainer;
2022-08-25 12:47:02 +03:00
ServerCredentials credentials = m_settings->serverCredentials(serverIndex);
2021-09-04 11:26:16 +03:00
2022-08-25 12:47:02 +03:00
QJsonObject protoConfig = m_settings->protocolConfig(serverIndex, container, Proto::Cloak);
2021-11-15 18:17:28 +03:00
QString cfg = protoConfig.value(config_key::last_config).toString();
2021-09-04 11:26:16 +03:00
2021-11-15 18:17:28 +03:00
if (cfg.isEmpty()) {
2022-08-25 12:47:02 +03:00
const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container);
2021-09-04 11:26:16 +03:00
2021-11-15 18:17:28 +03:00
ErrorCode e = ErrorCode::NoError;
2022-08-25 17:35:28 +03:00
cfg = m_configurator->cloakConfigurator->genCloakConfig(credentials, container, containerConfig, &e);
2021-11-15 18:17:28 +03:00
}
2021-09-04 11:26:16 +03:00
2021-11-15 18:17:28 +03:00
QJsonObject cloakConfig = QJsonDocument::fromJson(cfg.toUtf8()).object();
cloakConfig.remove(config_key::transport_proto);
cloakConfig.insert("ProxyMethod", "shadowsocks");
2021-09-04 11:26:16 +03:00
2021-11-15 18:17:28 +03:00
set_textEditShareCloakText(QJsonDocument(cloakConfig).toJson());
}
2021-09-04 11:26:16 +03:00
2021-11-15 18:17:28 +03:00
void ShareConnectionLogic::onPushButtonShareWireGuardGenerateClicked()
{
2023-02-20 09:46:50 +03:00
int serverIndex = uiLogic()->m_selectedServerIndex;
DockerContainer container = uiLogic()->m_selectedDockerContainer;
2022-08-25 12:47:02 +03:00
ServerCredentials credentials = m_settings->serverCredentials(serverIndex);
2021-09-04 11:26:16 +03:00
2022-08-25 12:47:02 +03:00
const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container);
2021-09-04 11:26:16 +03:00
2021-11-15 18:17:28 +03:00
ErrorCode e = ErrorCode::NoError;
2022-08-25 17:35:28 +03:00
QString cfg = m_configurator->wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig, &e);
2021-12-25 21:14:55 +03:00
if (e) {
2023-02-22 10:01:43 +03:00
emit uiLogic()->showWarningMessage(tr("Error occurred while generating the config.") + "\n" +
tr("Error message: ") + errorString(e) + "\n" +
tr("See logs for details."));
2021-12-25 21:14:55 +03:00
return;
}
2022-08-25 17:35:28 +03:00
cfg = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::WireGuard, cfg);
2021-11-15 18:17:28 +03:00
cfg = QJsonDocument::fromJson(cfg.toUtf8()).object()[config_key::config].toString();
2021-09-04 11:26:16 +03:00
2021-11-15 18:17:28 +03:00
set_textEditShareWireGuardCodeText(cfg);
2021-09-04 11:26:16 +03:00
2022-09-07 09:51:03 +03:00
QrCode qr = QrCode::encodeText(cfg.toUtf8(), QrCode::Ecc::LOW);
QString svg = QString::fromStdString(toSvgString(qr, 0));
2021-12-20 02:29:23 +03:00
2022-09-07 09:51:03 +03:00
set_shareWireGuardQrCodeText(svgToBase64(svg));
2021-11-15 18:17:28 +03:00
}
2021-09-04 11:26:16 +03:00
2021-11-15 18:17:28 +03:00
void ShareConnectionLogic::onPushButtonShareIkev2GenerateClicked()
{
2023-02-20 09:46:50 +03:00
int serverIndex = uiLogic()->m_selectedServerIndex;
DockerContainer container = uiLogic()->m_selectedDockerContainer;
2022-08-25 12:47:02 +03:00
ServerCredentials credentials = m_settings->serverCredentials(serverIndex);
2021-09-04 11:26:16 +03:00
2022-08-25 17:35:28 +03:00
Ikev2Configurator::ConnectionData connData = m_configurator->ikev2Configurator->prepareIkev2Config(credentials, container);
2021-09-04 11:26:16 +03:00
2022-08-25 17:35:28 +03:00
QString cfg = m_configurator->ikev2Configurator->genIkev2Config(connData);
cfg = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::Ikev2, cfg);
2021-11-15 18:17:28 +03:00
cfg = QJsonDocument::fromJson(cfg.toUtf8()).object()[config_key::cert].toString();
2021-09-04 11:26:16 +03:00
2021-11-15 18:17:28 +03:00
set_textEditShareIkev2CertText(cfg);
2021-09-04 11:26:16 +03:00
2022-08-25 17:35:28 +03:00
QString mobileCfg = m_configurator->ikev2Configurator->genMobileConfig(connData);
2021-11-15 18:17:28 +03:00
set_textEditShareIkev2MobileConfigText(mobileCfg);
2021-09-04 11:26:16 +03:00
2022-08-25 17:35:28 +03:00
QString strongSwanCfg = m_configurator->ikev2Configurator->genStrongSwanConfig(connData);
2021-11-15 18:17:28 +03:00
set_textEditShareIkev2StrongSwanConfigText(strongSwanCfg);
}
void ShareConnectionLogic::updateSharingPage(int serverIndex, DockerContainer container)
{
2023-02-20 09:46:50 +03:00
uiLogic()->m_selectedDockerContainer = container;
uiLogic()->m_selectedServerIndex = serverIndex;
2021-11-15 18:17:28 +03:00
set_shareFullAccess(container == DockerContainer::None);
2021-12-20 02:29:23 +03:00
m_shareAmneziaQrCodeTextSeries.clear();
set_shareAmneziaQrCodeTextSeriesLength(0);
2021-09-04 11:26:16 +03:00
}
2021-12-20 02:29:23 +03:00
QList<QString> ShareConnectionLogic::genQrCodeImageSeries(const QByteArray &data)
2021-09-04 11:26:16 +03:00
{
2022-09-07 09:51:03 +03:00
double k = 850;
2021-09-04 11:26:16 +03:00
2021-12-20 02:29:23 +03:00
quint8 chunksCount = std::ceil(data.size() / k);
QList<QString> chunks;
for (int i = 0; i < data.size(); i = i + k) {
QByteArray chunk;
QDataStream s(&chunk, QIODevice::WriteOnly);
s << amnezia::qrMagicCode << chunksCount << (quint8)std::round(i/k) << data.mid(i, k);
2021-09-04 11:26:16 +03:00
2021-12-20 02:29:23 +03:00
QByteArray ba = chunk.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
2021-09-04 11:26:16 +03:00
2022-09-07 09:51:03 +03:00
QrCode qr = QrCode::encodeText(ba, QrCode::Ecc::LOW);
QString svg = QString::fromStdString(toSvgString(qr, 0));
chunks.append(svgToBase64(svg));
2021-12-20 02:29:23 +03:00
}
2021-09-04 11:26:16 +03:00
2021-12-20 02:29:23 +03:00
return chunks;
2021-11-08 15:18:52 +03:00
}
2021-09-03 20:17:13 +03:00
2022-09-07 09:51:03 +03:00
QString ShareConnectionLogic::svgToBase64(const QString &image)
2021-11-08 15:18:52 +03:00
{
2022-09-07 09:51:03 +03:00
return "data:image/svg;base64," + QString::fromLatin1(image.toUtf8().toBase64().data());
2021-09-03 20:17:13 +03:00
}