added parsing of wireguard config parameters when importing native configs

This commit is contained in:
vladimir.kuznetsov 2023-09-19 18:45:06 +05:00
parent f62076d3fd
commit ff41b26e94

View file

@ -1,72 +1,73 @@
#include "StartPageLogic.h" #include "StartPageLogic.h"
#include "ViewConfigLogic.h" #include "ViewConfigLogic.h"
#include "core/errorstrings.h" #include "../uilogic.h"
#include "configurators/ssh_configurator.h" #include "configurators/ssh_configurator.h"
#include "configurators/vpn_configurator.h" #include "configurators/vpn_configurator.h"
#include "../uilogic.h" #include "core/errorstrings.h"
#include "utilities.h"
#include "core/servercontroller.h" #include "core/servercontroller.h"
#include "utilities.h"
#include <QEventLoop>
#include <QFileDialog> #include <QFileDialog>
#include <QStandardPaths> #include <QStandardPaths>
#include <QEventLoop>
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
#include <QJniObject> #include "../../platforms/android/android_controller.h"
#include "../../platforms/android/androidutils.h" #include "../../platforms/android/androidutils.h"
#include "../../platforms/android/android_controller.h" #include <QJniObject>
#endif #endif
#ifdef Q_OS_IOS #ifdef Q_OS_IOS
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#endif #endif
namespace { namespace
enum class ConfigTypes {
Amnezia,
OpenVpn,
WireGuard
};
ConfigTypes checkConfigFormat(const QString &config)
{ {
const QString openVpnConfigPatternCli = "client"; enum class ConfigTypes {
const QString openVpnConfigPatternProto1 = "proto tcp"; Amnezia,
const QString openVpnConfigPatternProto2 = "proto udp"; OpenVpn,
const QString openVpnConfigPatternDriver1 = "dev tun"; WireGuard
const QString openVpnConfigPatternDriver2 = "dev tap"; };
const QString wireguardConfigPatternSectionInterface = "[Interface]"; ConfigTypes checkConfigFormat(const QString &config)
const QString wireguardConfigPatternSectionPeer = "[Peer]"; {
const QString openVpnConfigPatternCli = "client";
const QString openVpnConfigPatternProto1 = "proto tcp";
const QString openVpnConfigPatternProto2 = "proto udp";
const QString openVpnConfigPatternDriver1 = "dev tun";
const QString openVpnConfigPatternDriver2 = "dev tap";
if (config.contains(openVpnConfigPatternCli) && const QString wireguardConfigPatternSectionInterface = "[Interface]";
(config.contains(openVpnConfigPatternProto1) || config.contains(openVpnConfigPatternProto2)) && const QString wireguardConfigPatternSectionPeer = "[Peer]";
(config.contains(openVpnConfigPatternDriver1) || config.contains(openVpnConfigPatternDriver2))) {
return ConfigTypes::OpenVpn; if (config.contains(openVpnConfigPatternCli)
} else if (config.contains(wireguardConfigPatternSectionInterface) && && (config.contains(openVpnConfigPatternProto1) || config.contains(openVpnConfigPatternProto2))
config.contains(wireguardConfigPatternSectionPeer)) && (config.contains(openVpnConfigPatternDriver1) || config.contains(openVpnConfigPatternDriver2))) {
return ConfigTypes::WireGuard; return ConfigTypes::OpenVpn;
return ConfigTypes::Amnezia; } else if (config.contains(wireguardConfigPatternSectionInterface)
} && config.contains(wireguardConfigPatternSectionPeer))
return ConfigTypes::WireGuard;
return ConfigTypes::Amnezia;
}
} }
StartPageLogic::StartPageLogic(UiLogic *logic, QObject *parent): StartPageLogic::StartPageLogic(UiLogic *logic, QObject *parent)
PageLogicBase(logic, parent), : PageLogicBase(logic, parent),
m_pushButtonConnectEnabled{true}, m_pushButtonConnectEnabled { true },
m_pushButtonConnectText{tr("Connect")}, m_pushButtonConnectText { tr("Connect") },
m_pushButtonConnectKeyChecked{false}, m_pushButtonConnectKeyChecked { false },
m_labelWaitInfoVisible{true}, m_labelWaitInfoVisible { true },
m_pushButtonBackFromStartVisible{true}, m_pushButtonBackFromStartVisible { true },
m_ipAddressPortRegex{Utils::ipAddressPortRegExp()} m_ipAddressPortRegex { Utils::ipAddressPortRegExp() }
{ {
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
// Set security screen for Android app // Set security screen for Android app
AndroidUtils::runOnAndroidThreadSync([]() { AndroidUtils::runOnAndroidThreadSync([]() {
QJniObject activity = AndroidUtils::getActivity(); QJniObject activity = AndroidUtils::getActivity();
QJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;"); QJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
if (window.isValid()){ if (window.isValid()) {
const int FLAG_SECURE = 8192; const int FLAG_SECURE = 8192;
window.callMethod<void>("addFlags", "(I)V", FLAG_SECURE); window.callMethod<void>("addFlags", "(I)V", FLAG_SECURE);
} }
@ -93,17 +94,13 @@ void StartPageLogic::onUpdatePage()
void StartPageLogic::onPushButtonConnect() void StartPageLogic::onPushButtonConnect()
{ {
if (pushButtonConnectKeyChecked()){ if (pushButtonConnectKeyChecked()) {
if (lineEditIpText().isEmpty() || if (lineEditIpText().isEmpty() || lineEditLoginText().isEmpty() || textEditSshKeyText().isEmpty()) {
lineEditLoginText().isEmpty() ||
textEditSshKeyText().isEmpty() ) {
set_labelWaitInfoText(tr("Please fill in all fields")); set_labelWaitInfoText(tr("Please fill in all fields"));
return; return;
} }
} else { } else {
if (lineEditIpText().isEmpty() || if (lineEditIpText().isEmpty() || lineEditLoginText().isEmpty() || lineEditPasswordText().isEmpty()) {
lineEditLoginText().isEmpty() ||
lineEditPasswordText().isEmpty() ) {
set_labelWaitInfoText(tr("Please fill in all fields")); set_labelWaitInfoText(tr("Please fill in all fields"));
return; return;
} }
@ -178,7 +175,8 @@ void StartPageLogic::onPushButtonConnect()
set_pushButtonConnectText(tr("Connect")); set_pushButtonConnectText(tr("Connect"));
uiLogic()->m_installCredentials = serverCredentials; uiLogic()->m_installCredentials = serverCredentials;
if (ok) emit uiLogic()->goToPage(Page::NewServer); if (ok)
emit uiLogic()->goToPage(Page::NewServer);
} }
void StartPageLogic::onPushButtonImport() void StartPageLogic::onPushButtonImport()
@ -189,22 +187,24 @@ void StartPageLogic::onPushButtonImport()
void StartPageLogic::onPushButtonImportOpenFile() void StartPageLogic::onPushButtonImportOpenFile()
{ {
QString fileName = UiLogic::getOpenFileName(Q_NULLPTR, tr("Open config file"), QString fileName = UiLogic::getOpenFileName(Q_NULLPTR, tr("Open config file"),
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.vpn *.ovpn *.conf"); QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),
if (fileName.isEmpty()) return; "*.vpn *.ovpn *.conf");
if (fileName.isEmpty())
return;
QFile file(fileName); QFile file(fileName);
#ifdef Q_OS_IOS #ifdef Q_OS_IOS
CFURLRef url = CFURLCreateWithFileSystemPath( CFURLRef url = CFURLCreateWithFileSystemPath(
kCFAllocatorDefault, CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(fileName.unicode()), kCFAllocatorDefault,
fileName.length()), CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(fileName.unicode()), fileName.length()),
kCFURLPOSIXPathStyle, 0); kCFURLPOSIXPathStyle, 0);
if (!CFURLStartAccessingSecurityScopedResource(url)) { if (!CFURLStartAccessingSecurityScopedResource(url)) {
qDebug() << "Could not access path " << QUrl::fromLocalFile(fileName).toString(); qDebug() << "Could not access path " << QUrl::fromLocalFile(fileName).toString();
} }
#endif #endif
file.open(QIODevice::ReadOnly); file.open(QIODevice::ReadOnly);
QByteArray data = file.readAll(); QByteArray data = file.readAll();
@ -242,8 +242,7 @@ bool StartPageLogic::importConnection(const QJsonObject &profile)
// check config // check config
uiLogic()->pageLogic<ViewConfigLogic>()->set_configJson(profile); uiLogic()->pageLogic<ViewConfigLogic>()->set_configJson(profile);
emit uiLogic()->goToPage(Page::ViewConfig); emit uiLogic()->goToPage(Page::ViewConfig);
} } else {
else {
qDebug() << "Failed to import profile"; qDebug() << "Failed to import profile";
qDebug().noquote() << QJsonDocument(profile).toJson(); qDebug().noquote() << QJsonDocument(profile).toJson();
return false; return false;
@ -314,7 +313,6 @@ bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config)
o[config_key::defaultContainer] = "amnezia-openvpn"; o[config_key::defaultContainer] = "amnezia-openvpn";
o[config_key::description] = m_settings->nextAvailableServerName(); o[config_key::description] = m_settings->nextAvailableServerName();
const static QRegularExpression dnsRegExp("dhcp-option DNS (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)"); const static QRegularExpression dnsRegExp("dhcp-option DNS (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)");
QRegularExpressionMatchIterator dnsMatch = dnsRegExp.globalMatch(config); QRegularExpressionMatchIterator dnsMatch = dnsRegExp.globalMatch(config);
if (dnsMatch.hasNext()) { if (dnsMatch.hasNext()) {
@ -338,9 +336,51 @@ bool StartPageLogic::importConnectionFromWireguardConfig(const QString &config)
QRegularExpressionMatch hostNameAndPortMatch = hostNameAndPortRegExp.match(config); QRegularExpressionMatch hostNameAndPortMatch = hostNameAndPortRegExp.match(config);
QString hostName; QString hostName;
QString port; QString port;
if (hostNameAndPortMatch.hasMatch()) { if (hostNameAndPortMatch.hasCaptured(1)) {
hostName = hostNameAndPortMatch.captured(1); hostName = hostNameAndPortMatch.captured(1);
} else {
return importConnection(QJsonObject());
}
if (hostNameAndPortMatch.hasCaptured(2)) {
port = hostNameAndPortMatch.captured(2); port = hostNameAndPortMatch.captured(2);
} else {
port = protocols::wireguard::defaultPort;
}
lastConfig[config_key::hostName] = hostName;
lastConfig[config_key::port] = port.toInt();
const static QRegularExpression clientPrivKeyRegExp("PrivateKey = (.*)");
QRegularExpressionMatch clientPrivKeyMatch = clientPrivKeyRegExp.match(config);
if (clientPrivKeyMatch.hasMatch()) {
lastConfig[config_key::client_priv_key] = clientPrivKeyMatch.captured(1);
} else {
return importConnection(QJsonObject());
}
const static QRegularExpression clientIpRegExp("Address = (\\d+\\.\\d+\\.\\d+\\.\\d+)");
QRegularExpressionMatch clientIpMatch = clientIpRegExp.match(config);
if (clientIpMatch.hasMatch()) {
lastConfig[config_key::client_ip] = clientIpMatch.captured(1);
} else {
return importConnection(QJsonObject());
}
const static QRegularExpression pskKeyRegExp("PresharedKey = (.*)");
QRegularExpressionMatch pskKeyMatch = pskKeyRegExp.match(config);
if (pskKeyMatch.hasMatch()) {
lastConfig[config_key::psk_key] = pskKeyMatch.captured(1);
} else {
return importConnection(QJsonObject());
}
const static QRegularExpression serverPubKeyRegExp("PublicKey = (.*)");
QRegularExpressionMatch serverPubKeyMatch = serverPubKeyRegExp.match(config);
if (serverPubKeyMatch.hasMatch()) {
lastConfig[config_key::server_pub_key] = serverPubKeyMatch.captured(1);
} else {
return importConnection(QJsonObject());
} }
QJsonObject wireguardConfig; QJsonObject wireguardConfig;
@ -361,7 +401,9 @@ bool StartPageLogic::importConnectionFromWireguardConfig(const QString &config)
o[config_key::defaultContainer] = "amnezia-wireguard"; o[config_key::defaultContainer] = "amnezia-wireguard";
o[config_key::description] = m_settings->nextAvailableServerName(); o[config_key::description] = m_settings->nextAvailableServerName();
const static QRegularExpression dnsRegExp("DNS = (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b).*(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)"); const static QRegularExpression dnsRegExp(
"DNS = "
"(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b).*(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)");
QRegularExpressionMatch dnsMatch = dnsRegExp.match(config); QRegularExpressionMatch dnsMatch = dnsRegExp.match(config);
if (dnsMatch.hasMatch()) { if (dnsMatch.hasMatch()) {
o[config_key::dns1] = dnsMatch.captured(1); o[config_key::dns1] = dnsMatch.captured(1);