Index: vpn/openconnect/nm-openconnect-service.h =================================================================== --- vpn/openconnect/nm-openconnect-service.h +++ vpn/openconnect/nm-openconnect-service.h @@ -42,6 +42,8 @@ #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_TOKEN_MODE "stoken_source" +#define NM_OPENCONNECT_KEY_TOKEN_SECRET "stoken_string" #define NM_OPENCONNECT_USER "nm-openconnect" Index: vpn/openconnect/openconnectprop.ui =================================================================== --- vpn/openconnect/openconnectprop.ui +++ vpn/openconnect/openconnectprop.ui @@ -6,8 +6,8 @@ 0 0 - 339 - 364 + 381 + 612 @@ -29,7 +29,7 @@ - Gateway: + &Gateway: leGateway @@ -59,7 +59,7 @@ - Proxy: + Pro&xy: leProxy @@ -141,7 +141,7 @@ - Private Key: + Private &Key: leUserPrivateKey @@ -172,6 +172,72 @@ + + + + Software Token Authentication + + + + + + Token Mode: + + + + + + + Token Secret: + + + + + + + + 0 + 0 + + + + + Disabled + + + + + TOTP - manually entered + + + + + HOTP - manually entered + + + + + Yubikey OATH + + + + + + + + false + + + + 0 + 0 + + + + + + + Index: vpn/openconnect/openconnectwidget.h =================================================================== --- vpn/openconnect/openconnectwidget.h +++ vpn/openconnect/openconnectwidget.h @@ -36,9 +36,13 @@ explicit OpenconnectSettingWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget *parent = 0); ~OpenconnectSettingWidget(); virtual void loadConfig(const NetworkManager::Setting::Ptr &setting); + virtual void loadSecrets(const NetworkManager::Setting::Ptr &setting); virtual QVariantMap setting() const; virtual bool isValid() const; +public Q_SLOTS: + void slotTokenModeChanged(int index); + private: OpenconnectSettingWidgetPrivate *const d_ptr; }; Index: vpn/openconnect/openconnectwidget.cpp =================================================================== --- vpn/openconnect/openconnectwidget.cpp +++ vpn/openconnect/openconnectwidget.cpp @@ -21,6 +21,7 @@ #include "openconnectwidget.h" #include +#include #include #include "ui_openconnectprop.h" @@ -33,6 +34,8 @@ public: Ui_OpenconnectProp ui; NetworkManager::VpnSetting::Ptr setting; + + enum TokenMode {Disabled = 0, TOTP, HOTP, YubiOATH}; }; OpenconnectSettingWidget::OpenconnectSettingWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget * parent) @@ -48,6 +51,10 @@ // Connect for validity check connect(d->ui.leGateway, &QLineEdit::textChanged, this, &OpenconnectSettingWidget::slotWidgetChanged); + connect(d->ui.leTokenSecret, &QTextEdit::textChanged, this, &OpenconnectSettingWidget::slotWidgetChanged); + + connect(d->ui.cmbTokenMode, (void (QComboBox::*)(int))&QComboBox::currentIndexChanged, + this, &OpenconnectSettingWidget::slotTokenModeChanged); KAcceleratorManager::manage(this); @@ -78,6 +85,31 @@ 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"); + + const QString tokenMode = dataMap[NM_OPENCONNECT_KEY_TOKEN_MODE]; + if (tokenMode.compare("totp") == 0) { + d->ui.cmbTokenMode->setCurrentIndex(OpenconnectSettingWidgetPrivate::TOTP); + } else if (tokenMode.compare("hotp") == 0) { + d->ui.cmbTokenMode->setCurrentIndex(OpenconnectSettingWidgetPrivate::HOTP); + } else if (tokenMode.compare("yubioath") == 0) { + d->ui.cmbTokenMode->setCurrentIndex(OpenconnectSettingWidgetPrivate::YubiOATH); + } else { + d->ui.cmbTokenMode->setCurrentIndex(OpenconnectSettingWidgetPrivate::Disabled); + } + + loadSecrets(setting); +} + +void OpenconnectSettingWidget::loadSecrets(const NetworkManager::Setting::Ptr &setting) +{ + Q_D(OpenconnectSettingWidget); + Q_UNUSED(setting) + + const NMStringMap secrets = d->setting->secrets(); + + if (d->ui.cmbProtocol->currentIndex() != OpenconnectSettingWidgetPrivate::Disabled) { + d->ui.leTokenSecret->setText(secrets.value(NM_OPENCONNECT_KEY_TOKEN_SECRET); + } } QVariantMap OpenconnectSettingWidget::setting() const @@ -88,6 +120,7 @@ setting.setServiceType(QLatin1String(NM_DBUS_SERVICE_OPENCONNECT)); NMStringMap data; + NMStringMap 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 +142,22 @@ } data.insert(QLatin1String(NM_OPENCONNECT_KEY_PEM_PASSPHRASE_FSID), d->ui.chkUseFsid->isChecked() ? "yes" : "no"); + if (d->ui.cmbTokenMode->currentIndex() != OpenconnectSettingWidgetPrivate::Disabled) { + switch (d->ui.cmbTokenMode->currentIndex()) { + case OpenconnectSettingWidgetPrivate::TOTP: + data.insert(QLatin1String(NM_OPENCONNECT_KEY_TOKEN_MODE), "totp"); + break; + case OpenconnectSettingWidgetPrivate::HOTP: + data.insert(QLatin1String(NM_OPENCONNECT_KEY_TOKEN_MODE), "hotp"); + break; + case OpenconnectSettingWidgetPrivate::YubiOATH: + data.insert(QLatin1String(NM_OPENCONNECT_KEY_TOKEN_MODE), "yubioath"); + break; + } + + secrets.insert(QLatin1String(NM_OPENCONNECT_KEY_TOKEN_SECRET), d->ui.leTokenSecret->toPlainText()); + } + // 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,7 +171,7 @@ 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(); } @@ -132,3 +181,16 @@ Q_D(const OpenconnectSettingWidget); return !d->ui.leGateway->text().isEmpty(); } + +void OpenconnectSettingWidget::slotTokenModeChanged(int index) +{ + Q_D(const OpenconnectSettingWidget); + switch (index) { + case OpenconnectSettingWidgetPrivate::Disabled: + d->ui.leTokenSecret->setEnabled(false); + d->ui.leTokenSecret->clear(); + break; + default: + d->ui.leTokenSecret->setEnabled(true); + } +}