Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[settings-vpn] Add method for parsing openfortivpn / forticlient prov…
…isioning files. Contributes to JB#51527
  • Loading branch information
inzanity committed Dec 2, 2020
1 parent a171cdb commit 8db7743
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 1 deletion.
124 changes: 124 additions & 0 deletions src/settingsvpnmodel.cpp
Expand Up @@ -36,6 +36,8 @@
#include <QCryptographicHash>
#include <QQmlEngine>
#include <QDir>
#include <QXmlQuery>
#include <QXmlResultItems>
#include "logging_p.h"
#include "vpnmanager.h"

Expand Down Expand Up @@ -607,6 +609,8 @@ QVariantMap SettingsVpnModel::processProvisioningFile(const QString &path, const
if (provisioningFile.open(QIODevice::ReadOnly)) {
if (type == QString("openvpn")) {
rv = processOpenVpnProvisioningFile(provisioningFile);
} else if (type == QStringLiteral("openfortivpn")) {
rv = processOpenfortivpnProvisioningFile(provisioningFile);
} else {
qWarning() << "Provisioning not currently supported for VPN type:" << type;
}
Expand Down Expand Up @@ -855,6 +859,126 @@ QVariantMap SettingsVpnModel::processOpenVpnProvisioningFile(QFile &provisioning
return rv;
}

QVariantMap SettingsVpnModel::processOpenfortivpnProvisioningFile(QFile &provisioningFile)
{
char first;
QVariantMap rv;
QStringList option;

if (provisioningFile.peek(&first, 1) != 1) {
return QVariantMap();
}

if (first == '<') {
QXmlQuery query;
QXmlResultItems entries;

if (!query.setFocus(&provisioningFile)) {
qWarning() << "Unable to read provisioning configuration file";
return QVariantMap();
}

query.setQuery(QStringLiteral("/forticlient_configuration/vpn/sslvpn/connections/connection"));
query.evaluateTo(&entries);
if (!query.isValid()) {
qWarning() << "Unable to query provisioning configuration file";
return QVariantMap();
}

for (QXmlItem entry = entries.next(); !entry.isNull(); entry = entries.next()) {
QXmlQuery subQuery(query.namePool());
QStringList name;
QStringList address;
QStringList userGroup;
subQuery.setFocus(entry);

// Other fields that might be of interest
// username
// password
// warn_invalid_server_certificate
subQuery.setQuery(QStringLiteral("normalize-space(name[1]/text())"));
subQuery.evaluateTo(&name);
subQuery.setQuery(QStringLiteral("normalize-space(server[1]/text())"));
subQuery.evaluateTo(&address);

if (!name[0].isEmpty()) {
rv.insert(QStringLiteral("Name"), name[0]);
}

if (!address[0].isEmpty()) {
int pos = address[0].indexOf(':');
if (pos == -1) {
rv.insert(QStringLiteral("Host"), address[0]);
} else {
rv.insert(QStringLiteral("Host"), address[0].left(pos));
rv.insert(QStringLiteral("openfortivpn.Port"), address[0].midRef(pos + 1).toInt());
}

// We have a connection address, ignore the rest.
break;
}
}

// There's also other boolean (1/0) options under sslvpn/options:
// preferred_dtls_tunnel
// no_dhcp_server_route
// keep_connection_alive
query.setQuery(QStringLiteral("normalize-space(/forticlient_configuration/vpn/sslvpn/options/disallow_invalid_server_certificate/text())"));
query.evaluateTo(&option);
if (option[0] == QLatin1String("0")) {
rv.insert(QStringLiteral("openfortivpn.AllowSelfSignedCert"), QStringLiteral("true"));
}

} else {
QTextStream is(&provisioningFile);

const QRegularExpression commentLine(QStringLiteral("^\\#"));
const QRegularExpression record(QStringLiteral("^\\s*([^=]+)\\s*=\\s*(.*?)\\s*$"));
#define ENTRY(x, y) { QStringLiteral(x), QStringLiteral(y) }
const QHash<QString, QString> fields {
ENTRY("host", "Host"),
ENTRY("port", "openfortivpn.Port"),
ENTRY("trusted-cert", "openfortivpn.TrustedCert"),
// possibly useful fields for the future, not supported by connman plugin
// ENTRY("username", "?"),
// ENTRY("password", "?"),
// ENTRY("no-ftm-push", "?"),
// ENTRY("realm", "?"),
// ENTRY("ca-file", "?"),
// ENTRY("user-cert", "?"),
// ENTRY("user-key", "?"),
// ENTRY("insercure-ssl", "?"),
// ENTRY("cipher-list", "?"),
// ENTRY("user-agent", "?"),
// ENTRY("hostcheck", "?"),
};
#undef ENTRY

while (!is.atEnd()) {
QString line(is.readLine());

if (line.contains(commentLine)) {
continue;
}

QRegularExpressionMatch match = record.match(line);

if (!match.hasMatch()) {
continue;
}

QString field = match.captured(1);
auto i = fields.find(field);

if (i != fields.end()) {
rv[i.value()] = match.captured(2);
}
}
}

return rv;
}

void SettingsVpnModel::updateBestState(VpnConnection::ConnectionState maxState)
{
if (bestState_ != maxState) {
Expand Down
1 change: 1 addition & 0 deletions src/settingsvpnmodel.h
Expand Up @@ -98,6 +98,7 @@ class SYSTEMSETTINGS_EXPORT SettingsVpnModel : public VpnModel
virtual void orderConnections(QVector<VpnConnection*> &connections) override;
bool compareConnections(const VpnConnection *i, const VpnConnection *j);
QVariantMap processOpenVpnProvisioningFile(QFile &provisioningFile);
QVariantMap processOpenfortivpnProvisioningFile(QFile &provisioningFile);
void updateBestState(VpnConnection::ConnectionState maxState);

private Q_SLOTS:
Expand Down
2 changes: 1 addition & 1 deletion src/src.pro
Expand Up @@ -2,7 +2,7 @@ TEMPLATE = lib
TARGET = systemsettings

CONFIG += qt create_pc create_prl no_install_prl c++11
QT += qml dbus systeminfo
QT += qml dbus systeminfo xmlpatterns
QT -= gui

CONFIG += c++11 hide_symbols link_pkgconfig
Expand Down

0 comments on commit 8db7743

Please sign in to comment.