diff --git a/vpn/openconnect/CMakeLists.txt b/vpn/openconnect/CMakeLists.txt --- a/vpn/openconnect/CMakeLists.txt +++ b/vpn/openconnect/CMakeLists.txt @@ -39,7 +39,7 @@ openconnectauthworkerthread.cpp ) - ki18n_wrap_ui(openconnect_SRCS openconnectprop.ui openconnectauth.ui) + ki18n_wrap_ui(openconnect_SRCS openconnectprop.ui openconnectauth.ui openconnectadvanced.ui) add_library(plasmanetworkmanagement_openconnectui ${openconnect_SRCS}) diff --git a/vpn/openconnect/nm-openconnect-service.h b/vpn/openconnect/nm-openconnect-service.h --- a/vpn/openconnect/nm-openconnect-service.h +++ b/vpn/openconnect/nm-openconnect-service.h @@ -42,6 +42,7 @@ #define NM_OPENCONNECT_KEY_PROXY "proxy" #define NM_OPENCONNECT_KEY_CSD_ENABLE "enable_csd_trojan" #define NM_OPENCONNECT_KEY_CSD_WRAPPER "csd_wrapper" +#define NM_OPENCONNECT_KEY_TRUSTED_CERT "trusted-cert" #define NM_OPENCONNECT_USER "nm-openconnect" diff --git a/vpn/openconnect/openconnectadvanced.ui b/vpn/openconnect/openconnectadvanced.ui new file mode 100644 --- /dev/null +++ b/vpn/openconnect/openconnectadvanced.ui @@ -0,0 +1,85 @@ + + + OpenconnectAdvancedWidget + + + + 0 + 0 + 400 + 145 + + + + + 0 + 0 + + + + + 400 + 100 + + + + + + + + 0 + 0 + + + + Security + + + + + + Trusted certificate: + + + + + + + + 0 + 0 + + + + 0123456789abcdef0123456789abcdef0123456789abcdef0123456789 + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/vpn/openconnect/openconnectauth.cpp b/vpn/openconnect/openconnectauth.cpp --- a/vpn/openconnect/openconnectauth.cpp +++ b/vpn/openconnect/openconnectauth.cpp @@ -82,6 +82,7 @@ int cancelPipes[2]; QList > serverLog; int passwordFormIndex; + QString trustedCert; enum LogLevels {Error = 0, Info, Debug, Trace}; }; @@ -196,6 +197,9 @@ const QString protocol = dataMap[NM_OPENCONNECT_KEY_PROTOCOL]; openconnect_set_protocol(d->vpninfo, OC3DUP(protocol == "juniper" ? "nc" : protocol.toUtf8().data())); } + if (!dataMap[NM_OPENCONNECT_KEY_TRUSTED_CERT].isEmpty()) { + d->trustedCert = OC3DUP(dataMap[NM_OPENCONNECT_KEY_TRUSTED_CERT]); + } } void OpenconnectAuthWidget::readSecrets() @@ -516,8 +520,7 @@ const QString host = QLatin1String(openconnect_get_hostname(d->vpninfo)); const QString port = QString::number(openconnect_get_port(d->vpninfo)); - const QString key = QString("certificate:%1:%2").arg(host, port); - const QString value = d->secrets.value(key); + const QString value = d->secrets.value(NM_OPENCONNECT_KEY_TRUSTED_CERT); #if !OPENCONNECT_CHECK_VER(5,0) #define openconnect_check_peer_cert_hash(v,d) strcmp(d, fingerprint.toUtf8().data()) @@ -559,20 +562,28 @@ icon->setPixmap(QIcon::fromTheme("dialog-information").pixmap(KIconLoader::SizeLarge)); infoText->setText(i18n("Check failed for certificate from VPN server \"%1\".\n" - "Reason: %2\nAccept it anyway?", openconnect_get_hostname(d->vpninfo),reason)); + "Reason: %2\nAccept it anyway?", openconnect_get_hostname(d->vpninfo), reason)); infoText->setWordWrap(true); certificate->setText(peerCert); QPointer dialog = new QDialog(this); dialog.data()->setWindowModality(Qt::WindowModal); dialog->setLayout(new QVBoxLayout); + + QCheckBox *checkBox = new QCheckBox("Accept permanently", dialog); + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, dialog); connect(buttons, &QDialogButtonBox::accepted, dialog.data(), &QDialog::accept); connect(buttons, &QDialogButtonBox::rejected, dialog.data(), &QDialog::reject); dialog->layout()->addWidget(widget); + dialog->layout()->addWidget(checkBox); dialog->layout()->addWidget(buttons); + if(dialog.data()->exec() == QDialog::Accepted) { *accepted = true; + if (checkBox->isChecked()) { + d->secrets.insert(NM_OPENCONNECT_KEY_TRUSTED_CERT, QString(fingerprint)); + } } else { *accepted = false; } @@ -583,9 +594,7 @@ } else { *accepted = true; } - if (*accepted) { - d->secrets.insert(key, QString(fingerprint)); - } + d->mutex.lock(); d->workerWaiting.wakeAll(); d->mutex.unlock(); @@ -629,7 +638,7 @@ QComboBox *cbo = qobject_cast(widget); QByteArray text = cbo->itemData(cbo->currentIndex()).toString().toAscii(); openconnect_set_option_value(opt, text.data()); - d->secrets.insert(key,cbo->itemData(cbo->currentIndex()).toString()); + d->secrets.insert(key, cbo->itemData(cbo->currentIndex()).toString()); } } } diff --git a/vpn/openconnect/openconnectprop.ui b/vpn/openconnect/openconnectprop.ui --- a/vpn/openconnect/openconnectprop.ui +++ b/vpn/openconnect/openconnectprop.ui @@ -6,15 +6,15 @@ 0 0 - 339 - 364 + 395 + 436 OpenConnect Settings - - + + General @@ -119,7 +119,7 @@ - + Certificate Authentication @@ -172,7 +172,27 @@ - + + + + Advanced + + + + + + + Qt::Horizontal + + + + 290 + 28 + + + + + Qt::Vertical @@ -190,7 +210,7 @@ KUrlRequester - QWidget + QFrame
kurlrequester.h
diff --git a/vpn/openconnect/openconnectwidget.h b/vpn/openconnect/openconnectwidget.h --- a/vpn/openconnect/openconnectwidget.h +++ b/vpn/openconnect/openconnectwidget.h @@ -36,9 +36,14 @@ explicit OpenconnectSettingWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget *parent = nullptr); ~OpenconnectSettingWidget() override; void loadConfig(const NetworkManager::Setting::Ptr &setting) override; + void loadSecrets(const NetworkManager::Setting::Ptr &setting) override; + QVariantMap setting() const override; bool isValid() const override; +private Q_SLOTS: + void showAdvanced(); + private: OpenconnectSettingWidgetPrivate *const d_ptr; }; diff --git a/vpn/openconnect/openconnectwidget.cpp b/vpn/openconnect/openconnectwidget.cpp --- a/vpn/openconnect/openconnectwidget.cpp +++ b/vpn/openconnect/openconnectwidget.cpp @@ -24,15 +24,19 @@ #include #include "ui_openconnectprop.h" +#include "ui_openconnectadvanced.h" #include +#include #include "nm-openconnect-service.h" class OpenconnectSettingWidgetPrivate { public: Ui_OpenconnectProp ui; + Ui_OpenconnectAdvancedWidget advUi; NetworkManager::VpnSetting::Ptr setting; + QDialog *advancedDlg; }; OpenconnectSettingWidget::OpenconnectSettingWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget * parent) @@ -49,6 +53,17 @@ // Connect for validity check connect(d->ui.leGateway, &QLineEdit::textChanged, this, &OpenconnectSettingWidget::slotWidgetChanged); + // Advanced configuration + connect(d->ui.advancedButton, &QPushButton::clicked, this, &OpenconnectSettingWidget::showAdvanced); + + d->advancedDlg = new QDialog(this); + d->advUi.setupUi(d->advancedDlg); + QVBoxLayout * layout = new QVBoxLayout(d->advancedDlg); + connect(d->advUi.buttonBox, &QDialogButtonBox::accepted, d->advancedDlg, &QDialog::accept); + connect(d->advUi.buttonBox, &QDialogButtonBox::rejected, d->advancedDlg, &QDialog::reject); + layout->addWidget(d->advancedDlg); + d->advancedDlg->setLayout(layout); + KAcceleratorManager::manage(this); if (d->setting) { @@ -64,7 +79,6 @@ void OpenconnectSettingWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { Q_D(OpenconnectSettingWidget); - Q_UNUSED(setting) // General settings const NMStringMap dataMap = d->setting->data(); @@ -78,6 +92,21 @@ d->ui.leUserCert->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENCONNECT_KEY_USERCERT])); d->ui.leUserPrivateKey->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENCONNECT_KEY_PRIVKEY])); d->ui.chkUseFsid->setChecked(dataMap[NM_OPENCONNECT_KEY_PEM_PASSPHRASE_FSID] == "yes"); + + loadSecrets(setting); +} + +void OpenconnectSettingWidget::loadSecrets(const NetworkManager::Setting::Ptr &setting) +{ + Q_D(OpenconnectSettingWidget); + + // From advanced dialog + NetworkManager::VpnSetting::Ptr vpnSetting = setting.staticCast(); + + if (vpnSetting) { + const NMStringMap secrets = vpnSetting->secrets(); + d->advUi.trustedCert->setText(secrets.value(NM_OPENCONNECT_KEY_TRUSTED_CERT)); + } } QVariantMap OpenconnectSettingWidget::setting() const @@ -88,6 +117,7 @@ setting.setServiceType(QLatin1String(NM_DBUS_SERVICE_OPENCONNECT)); NMStringMap data; + NMStringMap secrets = d->setting->secrets(); data.insert(NM_OPENCONNECT_KEY_PROTOCOL, d->ui.cmbProtocol->currentIndex() ? QLatin1String("nc") : QLatin1String("anyconnect")); data.insert(QLatin1String(NM_OPENCONNECT_KEY_GATEWAY), d->ui.leGateway->text()); @@ -109,6 +139,9 @@ } data.insert(QLatin1String(NM_OPENCONNECT_KEY_PEM_PASSPHRASE_FSID), d->ui.chkUseFsid->isChecked() ? "yes" : "no"); + // From advanced + secrets.insert(NM_OPENCONNECT_KEY_TRUSTED_CERT, d->advUi.trustedCert->text()); + // Restore previous flags, this is necessary for keeping secrets stored in KWallet Q_FOREACH (const QString &key, d->setting->data().keys()) { if (key.contains(QLatin1String("-flags"))) { @@ -122,11 +155,18 @@ data.insert(QLatin1String(NM_OPENCONNECT_KEY_GATEWAY"-flags"), QString::number(NetworkManager::Setting::NotSaved)); setting.setData(data); - setting.setSecrets(d->setting->secrets()); + setting.setSecrets(secrets); return setting.toMap(); } +void OpenconnectSettingWidget::showAdvanced() +{ + Q_D(OpenconnectSettingWidget); + + d->advancedDlg->show(); +} + bool OpenconnectSettingWidget::isValid() const { Q_D(const OpenconnectSettingWidget);