extended the validation of the contents of the imported file (#670)

Extended the validation of the contents of the imported file
This commit is contained in:
Nethius 2024-03-14 04:22:10 +07:00 committed by GitHub
parent 0a90fd110d
commit c5a5bfde69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 109 additions and 58 deletions

View file

@ -18,7 +18,9 @@ namespace
enum class ConfigTypes { enum class ConfigTypes {
Amnezia, Amnezia,
OpenVpn, OpenVpn,
WireGuard WireGuard,
Backup,
Invalid
}; };
ConfigTypes checkConfigFormat(const QString &config) ConfigTypes checkConfigFormat(const QString &config)
@ -32,7 +34,15 @@ namespace
const QString wireguardConfigPatternSectionInterface = "[Interface]"; const QString wireguardConfigPatternSectionInterface = "[Interface]";
const QString wireguardConfigPatternSectionPeer = "[Peer]"; const QString wireguardConfigPatternSectionPeer = "[Peer]";
if (config.contains(openVpnConfigPatternCli) const QString amneziaConfigPattern = "containers";
const QString amneziaFreeConfigPattern = "api_key";
const QString backupPattern = "Servers/serversList";
if (config.contains(backupPattern)) {
return ConfigTypes::Backup;
} else if (config.contains(amneziaConfigPattern) || config.contains(amneziaFreeConfigPattern)) {
return ConfigTypes::Amnezia;
} else if (config.contains(openVpnConfigPatternCli)
&& (config.contains(openVpnConfigPatternProto1) || config.contains(openVpnConfigPatternProto2)) && (config.contains(openVpnConfigPatternProto1) || config.contains(openVpnConfigPatternProto2))
&& (config.contains(openVpnConfigPatternDriver1) || config.contains(openVpnConfigPatternDriver2))) { && (config.contains(openVpnConfigPatternDriver1) || config.contains(openVpnConfigPatternDriver2))) {
return ConfigTypes::OpenVpn; return ConfigTypes::OpenVpn;
@ -40,7 +50,7 @@ namespace
&& config.contains(wireguardConfigPatternSectionPeer)) { && config.contains(wireguardConfigPatternSectionPeer)) {
return ConfigTypes::WireGuard; return ConfigTypes::WireGuard;
} }
return ConfigTypes::Amnezia; return ConfigTypes::Invalid;
} }
#if defined Q_OS_ANDROID #if defined Q_OS_ANDROID
@ -58,34 +68,65 @@ ImportController::ImportController(const QSharedPointer<ServersModel> &serversMo
#endif #endif
} }
void ImportController::extractConfigFromFile(const QString &fileName) bool ImportController::extractConfigFromFile(const QString &fileName)
{ {
QFile file(fileName); QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) { if (file.open(QIODevice::ReadOnly)) {
QString data = file.readAll(); QString data = file.readAll();
extractConfigFromData(data);
m_configFileName = QFileInfo(file.fileName()).fileName(); m_configFileName = QFileInfo(file.fileName()).fileName();
return extractConfigFromData(data);
} }
emit importErrorOccurred(tr("Unable to open file"));
return false;
} }
void ImportController::extractConfigFromData(QString data) bool ImportController::extractConfigFromData(QString data)
{ {
auto configFormat = checkConfigFormat(data); QString config = data;
if (configFormat == ConfigTypes::OpenVpn) { auto configFormat = checkConfigFormat(config);
m_config = extractOpenVpnConfig(data); if (configFormat == ConfigTypes::Invalid) {
} else if (configFormat == ConfigTypes::WireGuard) { data.replace("vpn://", "");
m_config = extractWireGuardConfig(data); QByteArray ba =
QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
QByteArray ba_uncompressed = qUncompress(ba);
if (!ba_uncompressed.isEmpty()) {
ba = ba_uncompressed;
}
config = ba;
configFormat = checkConfigFormat(config);
}
switch (configFormat) {
case ConfigTypes::OpenVpn: {
m_config = extractOpenVpnConfig(config);
return true;
}
case ConfigTypes::WireGuard: {
m_config = extractWireGuardConfig(config);
return true;
}
case ConfigTypes::Amnezia: {
m_config = QJsonDocument::fromJson(config.toUtf8()).object();
return true;
}
case ConfigTypes::Backup: {
if (!m_serversModel->getServersCount()) {
emit restoreAppConfig(config.toUtf8());
} else { } else {
m_config = extractAmneziaConfig(data); emit importErrorOccurred(tr("Invalid configuration file"));
} }
} break;
}
void ImportController::extractConfigFromCode(QString code) case ConfigTypes::Invalid: {
{ emit importErrorOccurred(tr("Invalid configuration file"));
m_config = extractAmneziaConfig(code); break;
m_configFileName = ""; }
}
return false;
} }
bool ImportController::extractConfigFromQr(const QByteArray &data) bool ImportController::extractConfigFromQr(const QByteArray &data)
@ -139,28 +180,13 @@ void ImportController::importConfig()
} else { } else {
qDebug() << "Failed to import profile"; qDebug() << "Failed to import profile";
qDebug().noquote() << QJsonDocument(m_config).toJson(); qDebug().noquote() << QJsonDocument(m_config).toJson();
emit importErrorOccurred(errorString(ErrorCode::ImportInvalidConfigError)); emit importErrorOccurred(errorString(ErrorCode::ImportInvalidConfigError), false);
} }
m_config = {}; m_config = {};
m_configFileName.clear(); m_configFileName.clear();
} }
QJsonObject ImportController::extractAmneziaConfig(QString &data)
{
data.replace("vpn://", "");
QByteArray ba = QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
QByteArray ba_uncompressed = qUncompress(ba);
if (!ba_uncompressed.isEmpty()) {
ba = ba_uncompressed;
}
QJsonObject config = QJsonDocument::fromJson(ba).object();
return config;
}
QJsonObject ImportController::extractOpenVpnConfig(const QString &data) QJsonObject ImportController::extractOpenVpnConfig(const QString &data)
{ {
QJsonObject openVpnConfig; QJsonObject openVpnConfig;
@ -229,8 +255,8 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
if (hostNameAndPortMatch.hasCaptured(1)) { if (hostNameAndPortMatch.hasCaptured(1)) {
hostName = hostNameAndPortMatch.captured(1); hostName = hostNameAndPortMatch.captured(1);
} else { } else {
qDebug() << "Failed to import profile"; qDebug() << "Key parameter 'Endpoint' is missing";
emit importErrorOccurred(errorString(ErrorCode::ImportInvalidConfigError)); emit importErrorOccurred(errorString(ErrorCode::ImportInvalidConfigError), false);
} }
if (hostNameAndPortMatch.hasCaptured(2)) { if (hostNameAndPortMatch.hasCaptured(2)) {
@ -242,10 +268,11 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
lastConfig[config_key::hostName] = hostName; lastConfig[config_key::hostName] = hostName;
lastConfig[config_key::port] = port.toInt(); lastConfig[config_key::port] = port.toInt();
// if (!configMap.value("PrivateKey").isEmpty() && !configMap.value("Address").isEmpty() if (!configMap.value("PrivateKey").isEmpty() && !configMap.value("Address").isEmpty()
// && !configMap.value("PresharedKey").isEmpty() && !configMap.value("PublicKey").isEmpty()) { && !configMap.value("PublicKey").isEmpty()) {
lastConfig[config_key::client_priv_key] = configMap.value("PrivateKey"); lastConfig[config_key::client_priv_key] = configMap.value("PrivateKey");
lastConfig[config_key::client_ip] = configMap.value("Address"); lastConfig[config_key::client_ip] = configMap.value("Address");
if (!configMap.value("PresharedKey").isEmpty()) { if (!configMap.value("PresharedKey").isEmpty()) {
lastConfig[config_key::psk_key] = configMap.value("PresharedKey"); lastConfig[config_key::psk_key] = configMap.value("PresharedKey");
} else if (!configMap.value("PreSharedKey").isEmpty()) { } else if (!configMap.value("PreSharedKey").isEmpty()) {
@ -253,11 +280,11 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
} }
lastConfig[config_key::server_pub_key] = configMap.value("PublicKey"); lastConfig[config_key::server_pub_key] = configMap.value("PublicKey");
// } else { } else {
// qDebug() << "Failed to import profile"; qDebug() << "One of the key parameters is missing (PrivateKey, Address, PublicKey)";
// emit importErrorOccurred(errorString(ErrorCode::ImportInvalidConfigError)); emit importErrorOccurred(errorString(ErrorCode::ImportInvalidConfigError));
// return QJsonObject(); return QJsonObject();
// } }
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configMap.value("AllowedIPs").split(",")); QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configMap.value("AllowedIPs").split(","));

View file

@ -18,9 +18,8 @@ public:
public slots: public slots:
void importConfig(); void importConfig();
void extractConfigFromFile(const QString &fileName); bool extractConfigFromFile(const QString &fileName);
void extractConfigFromData(QString data); bool extractConfigFromData(QString data);
void extractConfigFromCode(QString code);
bool extractConfigFromQr(const QByteArray &data); bool extractConfigFromQr(const QByteArray &data);
QString getConfig(); QString getConfig();
QString getConfigFileName(); QString getConfigFileName();
@ -39,12 +38,14 @@ public slots:
signals: signals:
void importFinished(); void importFinished();
void importErrorOccurred(const QString &errorMessage, bool goToPageHome = false); void importErrorOccurred(const QString &errorMessage, bool goToPageHome);
void importErrorOccurred(const QString &errorMessage);
void qrDecodingFinished(); void qrDecodingFinished();
void restoreAppConfig(const QByteArray &data);
private: private:
QJsonObject extractAmneziaConfig(QString &data);
QJsonObject extractOpenVpnConfig(const QString &data); QJsonObject extractOpenVpnConfig(const QString &data);
QJsonObject extractWireGuardConfig(const QString &data); QJsonObject extractWireGuardConfig(const QString &data);

View file

@ -113,6 +113,11 @@ void SettingsController::restoreAppConfig(const QString &fileName)
QByteArray data = file.readAll(); QByteArray data = file.readAll();
restoreAppConfigFromData(data);
}
void SettingsController::restoreAppConfigFromData(const QByteArray &data)
{
bool ok = m_settings->restoreAppConfig(data); bool ok = m_settings->restoreAppConfig(data);
if (ok) { if (ok) {
m_serversModel->resetModel(); m_serversModel->resetModel();

View file

@ -41,6 +41,7 @@ public slots:
void backupAppConfig(const QString &fileName); void backupAppConfig(const QString &fileName);
void restoreAppConfig(const QString &fileName); void restoreAppConfig(const QString &fileName);
void restoreAppConfigFromData(const QByteArray &data);
QString getAppVersion(); QString getAppVersion();

View file

@ -73,12 +73,7 @@ PageType {
"Config files (*.vpn *.ovpn *.conf)" "Config files (*.vpn *.ovpn *.conf)"
var fileName = SystemController.getFileName(qsTr("Open config file"), nameFilter) var fileName = SystemController.getFileName(qsTr("Open config file"), nameFilter)
if (fileName !== "") { if (fileName !== "") {
if (fileName.indexOf(".backup") !== -1 && !ServersModel.getServersCount()) { if (ImportController.extractConfigFromFile(fileName)) {
PageController.showBusyIndicator(true)
SettingsController.restoreAppConfig(fileName)
PageController.showBusyIndicator(false)
} else {
ImportController.extractConfigFromFile(fileName)
PageController.goToPage(PageEnum.PageSetupWizardViewConfig) PageController.goToPage(PageEnum.PageSetupWizardViewConfig)
} }
} }

View file

@ -81,6 +81,20 @@ PageType {
} }
} }
Connections {
target: ImportController
function onRestoreAppConfig(data) {
PageController.showBusyIndicator(true)
SettingsController.restoreAppConfigFromData(data)
PageController.showBusyIndicator(false)
}
function onImportErrorOccurred(errorMessage) {
PageController.showErrorMessage(errorMessage)
}
}
FlickableType { FlickableType {
id: fl id: fl
anchors.top: parent.top anchors.top: parent.top

View file

@ -77,7 +77,7 @@ PageType {
text: qsTr("Continue") text: qsTr("Continue")
clickedFunc: function() { clickedFunc: function() {
ImportController.extractConfigFromCode(textKey.textFieldText) ImportController.extractConfigFromData(textKey.textFieldText)
PageController.goToPage(PageEnum.PageSetupWizardViewConfig) PageController.goToPage(PageEnum.PageSetupWizardViewConfig)
} }
} }

View file

@ -121,6 +121,14 @@ PageType {
} }
} }
Connections {
target: ImportController
function onImportErrorOccurred(errorMessage) {
PageController.showErrorMessage(errorMessage)
}
}
StackViewType { StackViewType {
id: tabBarStackView id: tabBarStackView