diff --git a/libs/editor/settings/bondwidget.cpp b/libs/editor/settings/bondwidget.cpp index a0f2d1d3..b2186123 100644 --- a/libs/editor/settings/bondwidget.cpp +++ b/libs/editor/settings/bondwidget.cpp @@ -1,312 +1,316 @@ /* Copyright 2013 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "bondwidget.h" #include "ui_bond.h" #include "connectioneditordialog.h" #include "debug.h" #include #include #include #include #include #include #include #define NM_SETTING_BOND_OPTION_MII_MONITOR "mii" #define NM_SETTING_BOND_OPTION_ARP_MONITOR "arp" BondWidget::BondWidget(const QString & masterUuid, const QString &masterId, const NetworkManager::Setting::Ptr &setting, QWidget* parent, Qt::WindowFlags f): SettingWidget(setting, parent, f), m_uuid(masterUuid), m_id(masterId), m_ui(new Ui::BondWidget) { m_ui->setupUi(this); // Action buttons and menu m_menu = new QMenu(this); QAction * action = new QAction(i18n("Ethernet"), this); action->setData(NetworkManager::ConnectionSettings::Wired); m_menu->addAction(action); action = new QAction(i18n("InfiniBand"), this); action->setData(NetworkManager::ConnectionSettings::Infiniband); m_menu->addAction(action); m_ui->btnAdd->setMenu(m_menu); connect(m_menu, &QMenu::triggered, this, &BondWidget::addBond); connect(m_ui->btnEdit, &QPushButton::clicked, this, &BondWidget::editBond); connect(m_ui->btnDelete, &QPushButton::clicked, this, &BondWidget::deleteBond); // mode m_ui->mode->addItem(i18nc("bond mode", "Round-robin"), QLatin1String("balance-rr")); m_ui->mode->addItem(i18nc("bond mode", "Active backup"), QLatin1String("active-backup")); m_ui->mode->addItem(i18nc("bond mode", "Broadcast"), QLatin1String("broadcast")); m_ui->mode->addItem(i18nc("bond mode", "802.3ad"), QLatin1String("802.3ad")); m_ui->mode->addItem(i18nc("bond mode", "Adaptive transmit load balancing"), QLatin1String("balance-tlb")); m_ui->mode->addItem(i18nc("bond mode", "Adaptive load balancing"), QLatin1String("balance-alb")); // link monitor m_ui->linkMonitoring->addItem(i18nc("bond link monitoring", "MII (recommended)"), NM_SETTING_BOND_OPTION_MII_MONITOR); m_ui->linkMonitoring->addItem(i18nc("bond link monitoring", "ARP"), NM_SETTING_BOND_OPTION_ARP_MONITOR); // bonds populateBonds(); connect(m_ui->bonds, &QListWidget::currentItemChanged, this, &BondWidget::currentBondChanged); connect(m_ui->bonds, &QListWidget::itemDoubleClicked, this, &BondWidget::editBond); connect(m_ui->ifaceName, &KLineEdit::textChanged, this, &BondWidget::slotWidgetChanged); connect(m_ui->arpTargets, &KLineEdit::textChanged, this, &BondWidget::slotWidgetChanged); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->linkMonitoring, QOverload::of(&KComboBox::currentIndexChanged), this, &BondWidget::slotWidgetChanged); +#else + connect(m_ui->linkMonitoring, QOverload::of(&KComboBox::currentIndexChanged), this, &BondWidget::slotWidgetChanged); +#endif // Connect for setting check watchChangedSetting(); KAcceleratorManager::manage(this); KAcceleratorManager::manage(m_menu); if (setting) { loadConfig(setting); } } BondWidget::~BondWidget() { delete m_ui; } void BondWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { NetworkManager::BondSetting::Ptr bondSetting = setting.staticCast(); m_ui->ifaceName->setText(bondSetting->interfaceName()); const NMStringMap options = bondSetting->options(); // mode int modeIndex = m_ui->mode->findData(options.value(NM_SETTING_BOND_OPTION_MODE)); if (modeIndex == -1) modeIndex = 0; m_ui->mode->setCurrentIndex(modeIndex); const QString arpTargets = options.value(NM_SETTING_BOND_OPTION_ARP_IP_TARGET); if (!arpTargets.isEmpty()) { // ARP m_ui->linkMonitoring->setCurrentIndex(m_ui->linkMonitoring->findData(NM_SETTING_BOND_OPTION_ARP_MONITOR)); bool ok = false; const int arpMonFreq = options.value(NM_SETTING_BOND_OPTION_ARP_INTERVAL).toInt(&ok); if (ok && arpMonFreq > 0) m_ui->monitorFreq->setValue(arpMonFreq); m_ui->arpTargets->setText(arpTargets); } else { // MII m_ui->linkMonitoring->setCurrentIndex(m_ui->linkMonitoring->findData(NM_SETTING_BOND_OPTION_MII_MONITOR)); bool ok = false; const int miiMonFreq = options.value(NM_SETTING_BOND_OPTION_MIIMON).toInt(&ok); if (ok && miiMonFreq > 0) m_ui->monitorFreq->setValue(miiMonFreq); ok = false; const int upDelay = options.value(NM_SETTING_BOND_OPTION_UPDELAY).toInt(&ok); if (ok && upDelay > 0) m_ui->upDelay->setValue(upDelay); ok = false; const int downDelay = options.value(NM_SETTING_BOND_OPTION_DOWNDELAY).toInt(&ok); if (ok && downDelay > 0) m_ui->upDelay->setValue(downDelay); } } QVariantMap BondWidget::setting() const { NetworkManager::BondSetting setting; setting.setInterfaceName(m_ui->ifaceName->text()); NMStringMap options; options.insert(NM_SETTING_BOND_OPTION_MODE, m_ui->mode->itemData(m_ui->mode->currentIndex()).toString()); if (m_ui->linkMonitoring->itemData(m_ui->linkMonitoring->currentIndex()).toString() == NM_SETTING_BOND_OPTION_MII_MONITOR) { // MII options.insert(NM_SETTING_BOND_OPTION_MIIMON, QString::number(m_ui->monitorFreq->value())); const int upDelay = m_ui->upDelay->value(); if (upDelay) options.insert(NM_SETTING_BOND_OPTION_UPDELAY, QString::number(upDelay)); const int downDelay = m_ui->downDelay->value(); if (downDelay) options.insert(NM_SETTING_BOND_OPTION_DOWNDELAY, QString::number(downDelay)); } else { // ARP options.insert(NM_SETTING_BOND_OPTION_ARP_INTERVAL, QString::number(m_ui->monitorFreq->value())); const QString arpTargets = m_ui->arpTargets->text(); if (!arpTargets.isEmpty()) options.insert(NM_SETTING_BOND_OPTION_ARP_IP_TARGET, arpTargets); } setting.setOptions(options); return setting.toMap(); } void BondWidget::addBond(QAction *action) { qCDebug(PLASMA_NM) << "Adding bonded connection:" << action->data(); qCDebug(PLASMA_NM) << "Master UUID:" << m_uuid; qCDebug(PLASMA_NM) << "Slave type:" << type(); NetworkManager::ConnectionSettings::ConnectionType connectionType = static_cast(action->data().toInt()); NetworkManager::ConnectionSettings::Ptr connectionSettings = NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(connectionType)); connectionSettings->setUuid(NetworkManager::ConnectionSettings::createNewUuid()); connectionSettings->setMaster(m_uuid); connectionSettings->setSlaveType(type()); connectionSettings->setAutoconnect(false); QPointer bondEditor = new ConnectionEditorDialog(connectionSettings); connect(bondEditor.data(), &ConnectionEditorDialog::accepted, [bondEditor, this] () { qCDebug(PLASMA_NM) << "Saving slave connection"; // qCDebug(PLASMA_NM) << bondEditor->setting(); QDBusPendingReply reply = NetworkManager::addConnection(bondEditor->setting()); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, &BondWidget::bondAddComplete); }); connect(bondEditor.data(), &ConnectionEditorDialog::finished, [bondEditor] () { if (bondEditor) { bondEditor->deleteLater(); } }); bondEditor->setModal(true); bondEditor->show(); } void BondWidget::currentBondChanged(QListWidgetItem *current, QListWidgetItem *previous) { Q_UNUSED(previous) m_ui->btnEdit->setEnabled(current); m_ui->btnDelete->setEnabled(current); } void BondWidget::bondAddComplete(QDBusPendingCallWatcher * watcher) { QDBusPendingReply reply = *watcher; if (reply.isValid()) { // find the slave connection with matching UUID NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(reply.value().path()); if (connection && connection->settings()->master() == m_uuid) { const QString label = QString("%1 (%2)").arg(connection->name()).arg(connection->settings()->typeAsString(connection->settings()->connectionType())); QListWidgetItem * slaveItem = new QListWidgetItem(label, m_ui->bonds); slaveItem->setData(Qt::UserRole, connection->uuid()); slotWidgetChanged(); } } else { qCWarning(PLASMA_NM) << "Bonded connection not added:" << reply.error().message(); } } void BondWidget::editBond() { QListWidgetItem * currentItem = m_ui->bonds->currentItem(); if (!currentItem) return; const QString uuid = currentItem->data(Qt::UserRole).toString(); NetworkManager::Connection::Ptr connection = NetworkManager::findConnectionByUuid(uuid); if (connection) { // qCDebug(PLASMA_NM) << "Editing bonded connection" << currentItem->text() << uuid; QPointer bondEditor = new ConnectionEditorDialog(connection->settings()); connect(bondEditor.data(), &ConnectionEditorDialog::accepted, [connection, bondEditor, this] () { connection->update(bondEditor->setting()); connect(connection.data(), &NetworkManager::Connection::updated, this, &BondWidget::populateBonds); }); connect(bondEditor.data(), &ConnectionEditorDialog::finished, [bondEditor] () { if (bondEditor) { bondEditor->deleteLater(); } }); bondEditor->setModal(true); bondEditor->show(); } } void BondWidget::deleteBond() { QListWidgetItem * currentItem = m_ui->bonds->currentItem(); if (!currentItem) return; const QString uuid = currentItem->data(Qt::UserRole).toString(); NetworkManager::Connection::Ptr connection = NetworkManager::findConnectionByUuid(uuid); if (connection) { // qCDebug(PLASMA_NM) << "About to delete bonded connection" << currentItem->text() << uuid; if (KMessageBox::questionYesNo(this, i18n("Do you want to remove the connection '%1'?", connection->name()), i18n("Remove Connection"), KStandardGuiItem::remove(), KStandardGuiItem::no(), QString(), KMessageBox::Dangerous) == KMessageBox::Yes) { connection->remove(); delete currentItem; slotWidgetChanged(); } } } void BondWidget::populateBonds() { m_ui->bonds->clear(); for (const NetworkManager::Connection::Ptr &connection : NetworkManager::listConnections()) { NetworkManager::ConnectionSettings::Ptr settings = connection->settings(); // The mapping from slave to master may be by uuid or name, try our best to // figure out if we are master to the slave. const QString master = settings->master(); bool isSlave = ((master == m_uuid) || // by-uuid (!m_id.isEmpty() && master == m_id)); // by-name if (isSlave && (settings->slaveType() == type())) { const QString label = QString("%1 (%2)").arg(connection->name()).arg(connection->settings()->typeAsString(connection->settings()->connectionType())); QListWidgetItem * slaveItem = new QListWidgetItem(label, m_ui->bonds); slaveItem->setData(Qt::UserRole, connection->uuid()); } } } bool BondWidget::isValid() const { if (m_ui->linkMonitoring->itemData(m_ui->linkMonitoring->currentIndex()).toString() == NM_SETTING_BOND_OPTION_ARP_MONITOR) { const QStringList ipAddresses = m_ui->arpTargets->text().split(','); if (ipAddresses.isEmpty()) { return false; } for (const QString &ip : ipAddresses) { QHostAddress ipAddress(ip); if (ipAddress.isNull()) { return false; } } } return !m_ui->ifaceName->text().isEmpty() && m_ui->bonds->count() > 0; } diff --git a/libs/editor/settings/connectionwidget.cpp b/libs/editor/settings/connectionwidget.cpp index dcbb1fb6..b5629506 100644 --- a/libs/editor/settings/connectionwidget.cpp +++ b/libs/editor/settings/connectionwidget.cpp @@ -1,211 +1,223 @@ /* Copyright 2013 Jan Grulich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "connectionwidget.h" #include "ui_connectionwidget.h" #include "advancedpermissionswidget.h" #include #include #include #include #include #include #include #include #include #include ConnectionWidget::ConnectionWidget(const NetworkManager::ConnectionSettings::Ptr &settings, QWidget* parent, Qt::WindowFlags f): QWidget(parent, f), m_widget(new Ui::ConnectionWidget), m_type(settings->connectionType()), m_masterUuid(settings->master()), m_slaveType(settings->slaveType()) { m_widget->setupUi(this); m_widget->firewallZone->addItems(firewallZones()); // VPN combo populateVpnConnections(); if (settings->connectionType() == NetworkManager::ConnectionSettings::Vpn) { m_widget->autoconnectVpn->setEnabled(false); m_widget->vpnCombobox->setEnabled(false); m_widget->autoconnect->setEnabled(false); } else { m_widget->autoconnectVpn->setEnabled(true); m_widget->autoconnect->setEnabled(true); } connect(m_widget->autoconnectVpn, &QCheckBox::toggled, this, &ConnectionWidget::autoVpnToggled); if (settings) { loadConfig(settings); } m_tmpSetting.setPermissions(settings->permissions()); KAcceleratorManager::manage(this); connect(m_widget->autoconnect, &QCheckBox::stateChanged, this, &ConnectionWidget::settingChanged); connect(m_widget->allUsers, &QCheckBox::stateChanged, this, &ConnectionWidget::settingChanged); connect(m_widget->autoconnectVpn, &QCheckBox::stateChanged, this, &ConnectionWidget::settingChanged); connect(m_widget->pushButtonPermissions, &QPushButton::clicked, this, &ConnectionWidget::settingChanged); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_widget->firewallZone, QOverload::of(&QComboBox::currentIndexChanged), this, &ConnectionWidget::settingChanged); +#else + connect(m_widget->firewallZone, QOverload::of(&QComboBox::currentIndexChanged), this, &ConnectionWidget::settingChanged); +#endif connect(m_widget->firewallZone, &QComboBox::currentTextChanged, this, &ConnectionWidget::settingChanged); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_widget->vpnCombobox, QOverload::of(&QComboBox::currentIndexChanged), this, &ConnectionWidget::settingChanged); +#else + connect(m_widget->vpnCombobox, QOverload::of(&QComboBox::currentIndexChanged), this, &ConnectionWidget::settingChanged); +#endif connect(m_widget->vpnCombobox, &QComboBox::currentTextChanged, this, &ConnectionWidget::settingChanged); connect(m_widget->prioritySpin, QOverload::of(&QSpinBox::valueChanged), this, &ConnectionWidget::settingChanged); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_widget->metered, QOverload::of(&QComboBox::currentIndexChanged), this, &ConnectionWidget::settingChanged); +#else + connect(m_widget->metered, QOverload::of(&QComboBox::currentIndexChanged), this, &ConnectionWidget::settingChanged); +#endif connect(m_widget->pushButtonPermissions, &QPushButton::clicked, this, &ConnectionWidget::openAdvancedPermissions); } ConnectionWidget::~ConnectionWidget() { delete m_widget; } void ConnectionWidget::loadConfig(const NetworkManager::ConnectionSettings::Ptr &settings) { if (settings->permissions().isEmpty()) { m_widget->allUsers->setChecked(true); } else { m_widget->allUsers->setChecked(false); } const QString zone = settings->zone(); m_widget->firewallZone->setCurrentIndex(m_widget->firewallZone->findText(zone)); const QStringList secondaries = settings->secondaries(); const QStringList vpnKeys = vpnConnections().keys(); if (!secondaries.isEmpty() && !vpnKeys.isEmpty()) { for (const QString &vpnKey : vpnKeys) { if (secondaries.contains(vpnKey)) { m_widget->vpnCombobox->setCurrentIndex(m_widget->vpnCombobox->findData(vpnKey)); m_widget->autoconnectVpn->setChecked(true); break; } } } else { m_widget->autoconnectVpn->setChecked(false); } m_widget->autoconnect->setChecked(settings->autoconnect()); if (m_widget->prioritySpin->isEnabled()) { m_widget->prioritySpin->setValue(settings->autoconnectPriority()); } m_widget->metered->setCurrentIndex(settings->metered()); } NMVariantMapMap ConnectionWidget::setting() const { NetworkManager::ConnectionSettings settings; settings.setConnectionType(m_type); settings.setAutoconnect(m_widget->autoconnect->isChecked()); settings.setMaster(m_masterUuid); settings.setSlaveType(m_slaveType); if (m_widget->allUsers->isChecked()) { settings.setPermissions(QHash()); } else { if (m_tmpSetting.permissions().isEmpty()) { settings.addToPermissions(KUser().loginName(), QString()); } else { settings.setPermissions(m_tmpSetting.permissions()); } } if (m_widget->autoconnectVpn->isChecked() && m_widget->vpnCombobox->count() > 0) { settings.setSecondaries(QStringList() << m_widget->vpnCombobox->itemData(m_widget->vpnCombobox->currentIndex()).toString()); } const QString zone = m_widget->firewallZone->currentText(); if (!zone.isEmpty()) { settings.setZone(zone); } if (m_widget->prioritySpin->isEnabled()) { settings.setAutoconnectPriority(m_widget->prioritySpin->value()); } settings.setMetered(static_cast(m_widget->metered->currentIndex())); return settings.toMap(); } void ConnectionWidget::autoVpnToggled(bool on) { m_widget->vpnCombobox->setEnabled(on); } void ConnectionWidget::openAdvancedPermissions() { QPointer dialog = new AdvancedPermissionsWidget(m_tmpSetting.permissions(), this); dialog->setWindowTitle(i18nc("@title:window advanced permissions editor", "Advanced Permissions Editor")); if (dialog->exec() == QDialog::Accepted) { m_tmpSetting.setPermissions(dialog->currentUsers()); } delete dialog; } NMStringMap ConnectionWidget::vpnConnections() const { NetworkManager::Connection::List list = NetworkManager::listConnections(); NMStringMap result; for (const NetworkManager::Connection::Ptr &conn : list) { NetworkManager::ConnectionSettings::Ptr conSet = conn->settings(); if (conSet->connectionType() == NetworkManager::ConnectionSettings::Vpn || conSet->connectionType() == NetworkManager::ConnectionSettings::WireGuard) { // qCDebug(PLASMA_NM) << "Found VPN" << conSet->id() << conSet->uuid(); result.insert(conSet->uuid(), conSet->id()); } } return result; } QStringList ConnectionWidget::firewallZones() const { QDBusMessage msg = QDBusMessage::createMethodCall("org.fedoraproject.FirewallD1", "/org/fedoraproject/FirewallD1", "org.fedoraproject.FirewallD1.zone", "getZones"); QDBusPendingReply reply = QDBusConnection::systemBus().asyncCall(msg); reply.waitForFinished(); if (reply.isValid()) return reply.value(); return QStringList(); } void ConnectionWidget::populateVpnConnections() { QMapIterator it(vpnConnections()); while (it.hasNext()) { it.next(); m_widget->vpnCombobox->addItem(it.value(), it.key()); } } diff --git a/libs/editor/settings/ipv4widget.cpp b/libs/editor/settings/ipv4widget.cpp index 7bfb7304..3a02f761 100644 --- a/libs/editor/settings/ipv4widget.cpp +++ b/libs/editor/settings/ipv4widget.cpp @@ -1,566 +1,574 @@ /* Copyright (c) 2013 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "ipv4widget.h" #include "ui_ipv4.h" #include "ipv4delegate.h" #include #include #include #include #include #include #include #include #include #include quint32 suggestNetmask(quint32 ip) { /* A 0 0.0.0.0 <-->127.255.255.255 255.0.0.0 <--->/8 B 10 128.0.0.0 <>191.255.255.255 255.255.0.0 <->/16 C 110 192.0.0.0 <>223.255.255.255 255.255.255.0 >/24 D 1110 224.0.0.0 <>239.255.255.255 not defined <->not defined E 1111 240.0.0.0 <>255.255.255.254 not defined <->not defined */ quint32 netmask = 0; if (!(ip & 0x80000000)) { // test 0 leading bit netmask = 0xFF000000; } else if (!(ip & 0x40000000)) { // test 10 leading bits netmask = 0xFFFF0000; } else if (!(ip & 0x20000000)) { // test 110 leading bits netmask = 0xFFFFFF00; } return netmask; } class IPv4Widget::Private { public: Private() : model(0,3) { QStandardItem * headerItem = new QStandardItem(i18nc("Header text for IPv4 address", "Address")); model.setHorizontalHeaderItem(0, headerItem); headerItem = new QStandardItem(i18nc("Header text for IPv4 netmask", "Netmask")); model.setHorizontalHeaderItem(1, headerItem); headerItem = new QStandardItem(i18nc("Header text for IPv4 gateway", "Gateway")); model.setHorizontalHeaderItem(2, headerItem); } QStandardItemModel model; }; IPv4Widget::IPv4Widget(const NetworkManager::Setting::Ptr &setting, QWidget* parent, Qt::WindowFlags f): SettingWidget(setting, parent, f), m_ui(new Ui::IPv4Widget), d(new IPv4Widget::Private()) { m_ui->setupUi(this); m_ui->tableViewAddresses->setModel(&d->model); m_ui->tableViewAddresses->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); m_ui->tableViewAddresses->horizontalHeader()->setStretchLastSection(true); IpV4Delegate *ipDelegate = new IpV4Delegate(this); m_ui->tableViewAddresses->setItemDelegateForColumn(0, ipDelegate); m_ui->tableViewAddresses->setItemDelegateForColumn(1, ipDelegate); m_ui->tableViewAddresses->setItemDelegateForColumn(2, ipDelegate); connect(m_ui->btnAdd, &QPushButton::clicked, this, &IPv4Widget::slotAddIPAddress); connect(m_ui->btnRemove, &QPushButton::clicked, this, &IPv4Widget::slotRemoveIPAddress); connect(m_ui->dnsMorePushButton, &QPushButton::clicked, this, &IPv4Widget::slotDnsServers); connect(m_ui->dnsSearchMorePushButton, &QPushButton::clicked, this, &IPv4Widget::slotDnsDomains); connect(m_ui->tableViewAddresses->selectionModel(), &QItemSelectionModel::selectionChanged, this, &IPv4Widget::selectionChanged); connect(&d->model, &QStandardItemModel::itemChanged, this, &IPv4Widget::tableViewItemChanged); if (setting) { loadConfig(setting); } +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->method, QOverload::of(&KComboBox::currentIndexChanged), this, &IPv4Widget::slotModeComboChanged); +#else + connect(m_ui->method, QOverload::of(&KComboBox::currentIndexChanged), this, &IPv4Widget::slotModeComboChanged); +#endif slotModeComboChanged(m_ui->method->currentIndex()); connect(m_ui->btnRoutes, &QPushButton::clicked, this, &IPv4Widget::slotRoutesDialog); connect(m_ui->btnAdvanced, &QPushButton::clicked, this, &IPv4Widget::slotAdvancedDialog); // Connect for setting check watchChangedSetting(); // Connect for validity check connect(m_ui->dns, &KLineEdit::textChanged, this, &IPv4Widget::slotWidgetChanged); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->method, QOverload::of(&KComboBox::currentIndexChanged), this, &IPv4Widget::slotWidgetChanged); +#else + connect(m_ui->method, QOverload::of(&KComboBox::currentIndexChanged), this, &IPv4Widget::slotWidgetChanged); +#endif connect(&d->model, &QStandardItemModel::dataChanged, this, &IPv4Widget::slotWidgetChanged); connect(&d->model, &QStandardItemModel::rowsRemoved, this, &IPv4Widget::slotWidgetChanged); KAcceleratorManager::manage(this); } IPv4Widget::~IPv4Widget() { delete d; delete m_ui; } void IPv4Widget::loadConfig(const NetworkManager::Setting::Ptr &setting) { NetworkManager::Ipv4Setting::Ptr ipv4Setting = setting.staticCast(); // BUG:406118 // We don't have route-metric in the UI, maybe even won't have for now, but that doesn't mean we // want to loose it when it's configured manually in a config file m_tmpIpv4Setting.setRouteMetric(ipv4Setting->routeMetric()); m_tmpIpv4Setting.setRoutes(ipv4Setting->routes()); m_tmpIpv4Setting.setNeverDefault(ipv4Setting->neverDefault()); m_tmpIpv4Setting.setIgnoreAutoRoutes(ipv4Setting->ignoreAutoRoutes()); m_tmpIpv4Setting.setDhcpHostname(ipv4Setting->dhcpHostname()); m_tmpIpv4Setting.setDhcpSendHostname(ipv4Setting->dhcpSendHostname()); m_tmpIpv4Setting.setDadTimeout(ipv4Setting->dadTimeout()); // method switch (ipv4Setting->method()) { case NetworkManager::Ipv4Setting::Automatic: if (ipv4Setting->ignoreAutoDns()) { m_ui->method->setCurrentIndex(AutomaticOnlyIP); } else { m_ui->method->setCurrentIndex(Automatic); } break; case NetworkManager::Ipv4Setting::Manual: m_ui->method->setCurrentIndex(Manual); break; case NetworkManager::Ipv4Setting::LinkLocal: m_ui->method->setCurrentIndex(LinkLocal); break; case NetworkManager::Ipv4Setting::Shared: m_ui->method->setCurrentIndex(Shared); break; case NetworkManager::Ipv4Setting::Disabled: m_ui->method->setCurrentIndex(Disabled); break; } // dns QStringList tmp; for (const QHostAddress &addr : ipv4Setting->dns()) { tmp.append(addr.toString()); } m_ui->dns->setText(tmp.join(",")); m_ui->dnsSearch->setText(ipv4Setting->dnsSearch().join(",")); m_ui->dhcpClientId->setText(ipv4Setting->dhcpClientId()); // addresses for (const NetworkManager::IpAddress &addr : ipv4Setting->addresses()) { QList item; item << new QStandardItem(addr.ip().toString()) << new QStandardItem(addr.netmask().toString()) << new QStandardItem(addr.gateway().toString()); d->model.appendRow(item); } // may-fail m_ui->ipv4RequiredCB->setChecked(!ipv4Setting->mayFail()); } QVariantMap IPv4Widget::setting() const { NetworkManager::Ipv4Setting ipv4Setting; // BUG:406118 // We don't have route-metric in the UI, maybe even won't have for now, but that doesn't mean we // want to loose it when it's configured manually in a config file ipv4Setting.setRouteMetric(m_tmpIpv4Setting.routeMetric()); ipv4Setting.setRoutes(m_tmpIpv4Setting.routes()); ipv4Setting.setNeverDefault(m_tmpIpv4Setting.neverDefault()); ipv4Setting.setIgnoreAutoRoutes(m_tmpIpv4Setting.ignoreAutoRoutes()); ipv4Setting.setDhcpHostname(m_tmpIpv4Setting.dhcpHostname()); ipv4Setting.setDhcpSendHostname(m_tmpIpv4Setting.dhcpSendHostname()); ipv4Setting.setDadTimeout(m_tmpIpv4Setting.dadTimeout()); // method switch ((MethodIndex)m_ui->method->currentIndex()) { case Automatic: ipv4Setting.setMethod(NetworkManager::Ipv4Setting::Automatic); break; case IPv4Widget::AutomaticOnlyIP: ipv4Setting.setMethod(NetworkManager::Ipv4Setting::Automatic); ipv4Setting.setIgnoreAutoDns(true); break; case Manual: ipv4Setting.setMethod(NetworkManager::Ipv4Setting::Manual); break; case LinkLocal: ipv4Setting.setMethod(NetworkManager::Ipv4Setting::LinkLocal); break; case Shared: ipv4Setting.setMethod(NetworkManager::Ipv4Setting::Shared); break; case Disabled: ipv4Setting.setMethod(NetworkManager::Ipv4Setting::Disabled); break; } // dns if (m_ui->dns->isEnabled() && !m_ui->dns->text().isEmpty()) { QStringList tmp = m_ui->dns->text().split(','); QList tmpAddrList; for (const QString &str : tmp) { QHostAddress addr(str); if (!addr.isNull()) tmpAddrList.append(addr); } ipv4Setting.setDns(tmpAddrList); } if (m_ui->dnsSearch->isEnabled() && !m_ui->dnsSearch->text().isEmpty()) { ipv4Setting.setDnsSearch(m_ui->dnsSearch->text().split(',')); } // dhcp id if (m_ui->dhcpClientId->isEnabled() && !m_ui->dhcpClientId->text().isEmpty()) { ipv4Setting.setDhcpClientId(m_ui->dhcpClientId->text()); } // addresses if (m_ui->tableViewAddresses->isEnabled()) { QList list; for (int i = 0, rowCount = d->model.rowCount(); i < rowCount; i++) { NetworkManager::IpAddress address; address.setIp(QHostAddress(d->model.item(i, 0)->text())); address.setNetmask(QHostAddress(d->model.item(i, 1)->text())); address.setGateway(QHostAddress(d->model.item(i, 2)->text())); list << address; } if (!list.isEmpty()) { ipv4Setting.setAddresses(list); } } // may-fail if (m_ui->ipv4RequiredCB->isEnabled()) { ipv4Setting.setMayFail(!m_ui->ipv4RequiredCB->isChecked()); } return ipv4Setting.toMap(); } void IPv4Widget::slotModeComboChanged(int index) { if (index == Automatic) { // Automatic m_ui->dnsLabel->setText(i18n("Other DNS Servers:")); m_ui->dns->setEnabled(true); m_ui->dnsMorePushButton->setEnabled(true); m_ui->dnsSearch->setEnabled(true); m_ui->dnsSearchMorePushButton->setEnabled(true); m_ui->dhcpClientId->setEnabled(true); m_ui->ipv4RequiredCB->setEnabled(true); m_ui->btnRoutes->setEnabled(true); m_ui->tableViewAddresses->setEnabled(false); m_ui->btnAdd->setEnabled(false); m_ui->btnRemove->setEnabled(false); } else if (index == AutomaticOnlyIP) { m_ui->dnsLabel->setText(i18n("DNS Servers:")); m_ui->dns->setEnabled(true); m_ui->dnsMorePushButton->setEnabled(true); m_ui->dnsSearch->setEnabled(true); m_ui->dnsSearchMorePushButton->setEnabled(true); m_ui->dhcpClientId->setEnabled(true); m_ui->ipv4RequiredCB->setEnabled(true); m_ui->btnRoutes->setEnabled(true); m_ui->tableViewAddresses->setEnabled(false); m_ui->btnAdd->setEnabled(false); m_ui->btnRemove->setEnabled(false); } else if (index == Manual) { // Manual m_ui->dnsLabel->setText(i18n("DNS Servers:")); m_ui->dns->setEnabled(true); m_ui->dnsMorePushButton->setEnabled(true); m_ui->dnsSearch->setEnabled(true); m_ui->dnsSearchMorePushButton->setEnabled(true); m_ui->dhcpClientId->setEnabled(false); m_ui->ipv4RequiredCB->setEnabled(true); m_ui->btnRoutes->setEnabled(true); m_ui->tableViewAddresses->setEnabled(true); m_ui->btnAdd->setEnabled(true); m_ui->btnRemove->setEnabled(true); } else if (index == LinkLocal || index == Shared) { // Link-local or Shared m_ui->dnsLabel->setText(i18n("DNS Servers:")); m_ui->dns->setEnabled(false); m_ui->dnsMorePushButton->setEnabled(false); m_ui->dnsSearch->setEnabled(false); m_ui->dnsSearchMorePushButton->setEnabled(false); m_ui->dhcpClientId->setEnabled(false); m_ui->ipv4RequiredCB->setEnabled(true); m_ui->btnRoutes->setEnabled(false); m_ui->tableViewAddresses->setEnabled(false); m_ui->btnAdd->setEnabled(false); m_ui->btnRemove->setEnabled(false); } else if (index == Disabled) { // Disabled m_ui->dnsLabel->setText(i18n("DNS Servers:")); m_ui->dns->setEnabled(false); m_ui->dnsMorePushButton->setEnabled(false); m_ui->dnsSearch->setEnabled(false); m_ui->dnsSearchMorePushButton->setEnabled(false); m_ui->dhcpClientId->setEnabled(false); m_ui->ipv4RequiredCB->setEnabled(false); m_ui->btnRoutes->setEnabled(false); m_ui->tableViewAddresses->setEnabled(false); m_ui->btnAdd->setEnabled(false); m_ui->btnRemove->setEnabled(false); } } void IPv4Widget::slotAddIPAddress() { QList item; item << new QStandardItem << new QStandardItem << new QStandardItem; d->model.appendRow(item); const int rowCount = d->model.rowCount(); if (rowCount > 0) { m_ui->tableViewAddresses->selectRow(rowCount - 1); QItemSelectionModel * selectionModel = m_ui->tableViewAddresses->selectionModel(); QModelIndexList list = selectionModel->selectedIndexes(); if (!list.isEmpty()) { // QTableView is configured to select only rows. // So, list[0] - IP address. m_ui->tableViewAddresses->edit(list[0]); } } } void IPv4Widget::slotRemoveIPAddress() { QItemSelectionModel * selectionModel = m_ui->tableViewAddresses->selectionModel(); if (selectionModel->hasSelection()) { QModelIndexList indexes = selectionModel->selectedIndexes(); d->model.takeRow(indexes[0].row()); } m_ui->btnRemove->setEnabled(m_ui->tableViewAddresses->selectionModel()->hasSelection()); } void IPv4Widget::selectionChanged(const QItemSelection & selected) { m_ui->btnRemove->setEnabled(!selected.isEmpty()); } void IPv4Widget::tableViewItemChanged(QStandardItem *item) { if (item->text().isEmpty()) { return; } const int column = item->column(); if (column == 0) { // ip int row = item->row(); QStandardItem *netmaskItem = d->model.item(row, column + 1); // netmask if (netmaskItem && netmaskItem->text().isEmpty()) { QHostAddress addr(item->text()); const quint32 netmask = suggestNetmask(addr.toIPv4Address()); if (netmask) { QHostAddress v(netmask); netmaskItem->setText(v.toString()); } } } } void IPv4Widget::slotRoutesDialog() { QPointer dlg = new IpV4RoutesWidget(this); dlg->setRoutes(m_tmpIpv4Setting.routes()); dlg->setNeverDefault(m_tmpIpv4Setting.neverDefault()); if (m_ui->method->currentIndex() == 2) { // manual dlg->setIgnoreAutoRoutesCheckboxEnabled(false); } else { dlg->setIgnoreAutoRoutes(m_tmpIpv4Setting.ignoreAutoRoutes()); } connect(dlg.data(), &QDialog::accepted, [dlg, this] () { m_tmpIpv4Setting.setRoutes(dlg->routes()); m_tmpIpv4Setting.setNeverDefault(dlg->neverDefault()); m_tmpIpv4Setting.setIgnoreAutoRoutes(dlg->ignoreautoroutes()); }); connect(dlg.data(), &QDialog::finished, [dlg] () { if (dlg) { dlg->deleteLater(); } }); dlg->setModal(true); dlg->show(); } void IPv4Widget::slotAdvancedDialog() { auto dlg = new QDialog(this); dlg->setAttribute(Qt::WA_DeleteOnClose); auto layout = new QFormLayout(dlg); dlg->setLayout(layout); layout->addRow(new QLabel(i18n("You can find more information about these values here:
https://developer.gnome.org/NetworkManager/stable/nm-settings.html
"))); auto sendHostname = new QCheckBox(dlg); sendHostname->setChecked(m_tmpIpv4Setting.dhcpSendHostname()); layout->addRow(i18n("Send hostname:"), sendHostname); auto dhcpHostname = new QLineEdit(dlg); dhcpHostname->setText(m_tmpIpv4Setting.dhcpHostname()); dhcpHostname->setPlaceholderText(QHostInfo::localHostName()); layout->addRow(i18n("DHCP hostname:"), dhcpHostname); connect(sendHostname, &QCheckBox::toggled, dhcpHostname, &QLineEdit::setEnabled); auto dadTimeout = new QSpinBox(dlg); dadTimeout->setSpecialValueText(i18n("Default")); dadTimeout->setSuffix(i18nc("Milliseconds", " ms")); dadTimeout->setMinimum(-1); dadTimeout->setValue(m_tmpIpv4Setting.dadTimeout()); layout->addRow(i18n("DAD timeout:"), dadTimeout); QDialogButtonBox* box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, dlg); connect(box, &QDialogButtonBox::accepted, dlg, &QDialog::accept); connect(box, &QDialogButtonBox::rejected, dlg, &QDialog::reject); layout->addWidget(box); connect(dlg, &QDialog::accepted, this, [=] () { m_tmpIpv4Setting.setDhcpSendHostname(sendHostname->isChecked()); m_tmpIpv4Setting.setDhcpHostname(dhcpHostname->text()); m_tmpIpv4Setting.setDadTimeout(dadTimeout->value()); }); dlg->setModal(true); dlg->show(); } void IPv4Widget::slotDnsServers() { QPointer dialog = new QDialog(this); dialog->setWindowTitle(i18n("Edit DNS servers")); dialog->setLayout(new QVBoxLayout); 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); KEditListWidget * listWidget = new KEditListWidget(dialog); listWidget->setItems(m_ui->dns->text().split(',').replaceInStrings(" ", "")); listWidget->lineEdit()->setFocus(Qt::OtherFocusReason); dialog->layout()->addWidget(listWidget); dialog->layout()->addWidget(buttons); connect(dialog.data(), &QDialog::accepted, [listWidget, this] () { QString text = listWidget->items().join(","); if (text.endsWith(',')) { text.chop(1); } m_ui->dns->setText(text); }); connect(dialog.data(), &QDialog::finished, [dialog] () { if (dialog) { dialog->deleteLater(); } }); dialog->setModal(true); dialog->show(); } void IPv4Widget::slotDnsDomains() { QPointer dialog = new QDialog(this); dialog->setWindowTitle(i18n("Edit DNS search domains")); dialog->setLayout(new QVBoxLayout); 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); KEditListWidget * listWidget = new KEditListWidget(dialog); listWidget->setItems(m_ui->dnsSearch->text().split(',').replaceInStrings(" ", "")); listWidget->lineEdit()->setFocus(Qt::OtherFocusReason); dialog->layout()->addWidget(listWidget); dialog->layout()->addWidget(buttons); connect(dialog.data(), &QDialog::accepted, [listWidget, this] () { QString text = listWidget->items().join(","); if (text.endsWith(',')) { text.chop(1); } m_ui->dnsSearch->setText(text); }); connect(dialog.data(), &QDialog::finished, [dialog] () { if (dialog) { dialog->deleteLater(); } }); dialog->setModal(true); dialog->show(); } bool IPv4Widget::isValid() const { if (m_ui->method->currentIndex() == Manual) { if (!d->model.rowCount()) { return false; } for (int i = 0, rowCount = d->model.rowCount(); i < rowCount; i++) { QHostAddress ip = QHostAddress(d->model.item(i, 0)->text()); QHostAddress netmask = QHostAddress(d->model.item(i, 1)->text()); QHostAddress gateway = QHostAddress(d->model.item(i, 2)->text()); if (ip.isNull() || netmask.isNull() || (gateway.isNull() && !d->model.item(i, 2)->text().isEmpty())) { return false; } } } if (!m_ui->dns->text().isEmpty() && (m_ui->method->currentIndex() == Automatic || m_ui->method->currentIndex() == Manual || m_ui->method->currentIndex() == AutomaticOnlyIP)) { const QStringList tmp = m_ui->dns->text().split(','); for (const QString &str : tmp) { QHostAddress addr(str); if (addr.isNull()) { return false; } } } return true; } diff --git a/libs/editor/settings/ipv6widget.cpp b/libs/editor/settings/ipv6widget.cpp index f6ac8c1e..cfb6123f 100644 --- a/libs/editor/settings/ipv6widget.cpp +++ b/libs/editor/settings/ipv6widget.cpp @@ -1,501 +1,509 @@ /* Copyright (c) 2013 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "ipv6widget.h" #include "ui_ipv6.h" #include "ipv6delegate.h" #include "intdelegate.h" #include #include #include #include #include #include #include quint32 suggestNetmask(Q_IPV6ADDR ip) { Q_UNUSED(ip); /* TODO: find out common IPv6-netmasks and make a complete function */ quint32 netmask = 64; return netmask; } class IPv6Widget::Private { public: Private() : model(0,3) { QStandardItem * headerItem = new QStandardItem(i18nc("Header text for IPv6 address", "Address")); model.setHorizontalHeaderItem(0, headerItem); headerItem = new QStandardItem(i18nc("Header text for IPv6 prefix", "Prefix")); model.setHorizontalHeaderItem(1, headerItem); headerItem = new QStandardItem(i18nc("Header text for IPv6 gateway", "Gateway")); model.setHorizontalHeaderItem(2, headerItem); } QStandardItemModel model; }; IPv6Widget::IPv6Widget(const NetworkManager::Setting::Ptr &setting, QWidget* parent, Qt::WindowFlags f): SettingWidget(setting, parent, f), m_ui(new Ui::IPv6Widget), d(new IPv6Widget::Private()) { m_ui->setupUi(this); m_ui->tableViewAddresses->setModel(&d->model); m_ui->tableViewAddresses->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); m_ui->tableViewAddresses->horizontalHeader()->setStretchLastSection(true); IpV6Delegate *ipDelegate = new IpV6Delegate(this); IntDelegate *prefixDelegate = new IntDelegate (0, 128, this); m_ui->tableViewAddresses->setItemDelegateForColumn(0, ipDelegate); m_ui->tableViewAddresses->setItemDelegateForColumn(1, prefixDelegate); m_ui->tableViewAddresses->setItemDelegateForColumn(2, ipDelegate); connect(m_ui->btnAdd, &QPushButton::clicked, this, &IPv6Widget::slotAddIPAddress); connect(m_ui->btnRemove, &QPushButton::clicked, this, &IPv6Widget::slotRemoveIPAddress); connect(m_ui->dnsMorePushButton, &QPushButton::clicked, this, &IPv6Widget::slotDnsServers); connect(m_ui->dnsSearchMorePushButton, &QPushButton::clicked, this, &IPv6Widget::slotDnsDomains); connect(m_ui->tableViewAddresses->selectionModel(), &QItemSelectionModel::selectionChanged, this, &IPv6Widget::selectionChanged); connect(&d->model, &QStandardItemModel::itemChanged, this, &IPv6Widget::tableViewItemChanged); if (setting) { loadConfig(setting); } +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->method, QOverload::of(&KComboBox::currentIndexChanged), this, &IPv6Widget::slotModeComboChanged); +#else + connect(m_ui->method, QOverload::of(&KComboBox::currentIndexChanged), this, &IPv6Widget::slotModeComboChanged); +#endif slotModeComboChanged(m_ui->method->currentIndex()); connect(m_ui->btnRoutes, &QPushButton::clicked, this, &IPv6Widget::slotRoutesDialog); // Connect for setting check watchChangedSetting(); // Connect for validity check connect(m_ui->dns, &KLineEdit::textChanged, this, &IPv6Widget::slotWidgetChanged); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->method, QOverload::of(&KComboBox::currentIndexChanged), this, &IPv6Widget::slotWidgetChanged); +#else + connect(m_ui->method, QOverload::of(&KComboBox::currentIndexChanged), this, &IPv6Widget::slotWidgetChanged); +#endif connect(&d->model, &QStandardItemModel::dataChanged, this, &IPv6Widget::slotWidgetChanged); connect(&d->model, &QStandardItemModel::rowsRemoved, this, &IPv6Widget::slotWidgetChanged); KAcceleratorManager::manage(this); } IPv6Widget::~IPv6Widget() { delete d; delete m_ui; } void IPv6Widget::loadConfig(const NetworkManager::Setting::Ptr &setting) { NetworkManager::Ipv6Setting::Ptr ipv6Setting = setting.staticCast(); // BUG:406118 // We don't have route-metric in the UI, maybe even won't have for now, but that doesn't mean we // want to loose it when it's configured manually in a config file m_tmpIpv6Setting.setRouteMetric(ipv6Setting->routeMetric()); m_tmpIpv6Setting.setRoutes(ipv6Setting->routes()); m_tmpIpv6Setting.setNeverDefault(ipv6Setting->neverDefault()); m_tmpIpv6Setting.setIgnoreAutoRoutes(ipv6Setting->ignoreAutoRoutes()); // method switch (ipv6Setting->method()) { case NetworkManager::Ipv6Setting::Automatic: if (ipv6Setting->ignoreAutoDns()) { m_ui->method->setCurrentIndex(AutomaticOnlyIP); } else { m_ui->method->setCurrentIndex(Automatic); } break; case NetworkManager::Ipv6Setting::Dhcp: m_ui->method->setCurrentIndex(AutomaticOnlyDHCP); break; case NetworkManager::Ipv6Setting::Manual: m_ui->method->setCurrentIndex(Manual); break; case NetworkManager::Ipv6Setting::LinkLocal: m_ui->method->setCurrentIndex(LinkLocal); break; case NetworkManager::Ipv6Setting::Ignored: m_ui->method->setCurrentIndex(Disabled); break; } // dns QStringList tmp; for (const QHostAddress &addr : ipv6Setting->dns()) { tmp.append(addr.toString()); } m_ui->dns->setText(tmp.join(",")); m_ui->dnsSearch->setText(ipv6Setting->dnsSearch().join(",")); // addresses for (const NetworkManager::IpAddress &address : ipv6Setting->addresses()) { QList item; item << new QStandardItem(address.ip().toString()) << new QStandardItem(QString::number(address.prefixLength(),10)) << new QStandardItem(address.gateway().toString()); d->model.appendRow(item); } // may-fail m_ui->ipv6RequiredCB->setChecked(!ipv6Setting->mayFail()); // privacy if (ipv6Setting->privacy() != NetworkManager::Ipv6Setting::Unknown) { m_ui->privacyCombo->setCurrentIndex(static_cast(ipv6Setting->privacy()) + 1); } } QVariantMap IPv6Widget::setting() const { NetworkManager::Ipv6Setting ipv6Setting; // BUG:406118 // We don't have route-metric in the UI, maybe even won't have for now, but that doesn't mean we // want to loose it when it's configured manually in a config file ipv6Setting.setRouteMetric(m_tmpIpv6Setting.routeMetric()); ipv6Setting.setRoutes(m_tmpIpv6Setting.routes()); ipv6Setting.setNeverDefault(m_tmpIpv6Setting.neverDefault()); ipv6Setting.setIgnoreAutoRoutes(m_tmpIpv6Setting.ignoreAutoRoutes()); // method switch ((MethodIndex)m_ui->method->currentIndex()) { case Automatic: ipv6Setting.setMethod(NetworkManager::Ipv6Setting::Automatic); break; case AutomaticOnlyIP: ipv6Setting.setMethod(NetworkManager::Ipv6Setting::Automatic); ipv6Setting.setIgnoreAutoDns(true); break; case IPv6Widget::AutomaticOnlyDHCP: ipv6Setting.setMethod(NetworkManager::Ipv6Setting::Dhcp); break; case Manual: ipv6Setting.setMethod(NetworkManager::Ipv6Setting::Manual); break; case LinkLocal: ipv6Setting.setMethod(NetworkManager::Ipv6Setting::LinkLocal); break; case Disabled: ipv6Setting.setMethod(NetworkManager::Ipv6Setting::Ignored); break; } // dns if (m_ui->dns->isEnabled() && !m_ui->dns->text().isEmpty()) { QStringList tmp = m_ui->dns->text().split(','); QList tmpAddrList; for (const QString &str : tmp) { QHostAddress addr(str); if (!addr.isNull()) tmpAddrList.append(addr); } ipv6Setting.setDns(tmpAddrList); } if (m_ui->dnsSearch->isEnabled() && !m_ui->dnsSearch->text().isEmpty()) { ipv6Setting.setDnsSearch(m_ui->dnsSearch->text().split(',')); } // addresses if (m_ui->tableViewAddresses->isEnabled()) { QList list; for (int i = 0, rowCount = d->model.rowCount(); i < rowCount; i++) { NetworkManager::IpAddress address; address.setIp(QHostAddress(d->model.item(i, 0)->text())); address.setPrefixLength(d->model.item(i, 1)->text().toInt()); address.setGateway(QHostAddress(d->model.item(i, 2)->text())); list << address; } ipv6Setting.setAddresses(list); } // may-fail if (m_ui->ipv6RequiredCB->isEnabled()) { ipv6Setting.setMayFail(!m_ui->ipv6RequiredCB->isChecked()); } // privacy if (m_ui->privacyCombo->isEnabled() && m_ui->privacyCombo->currentIndex()) { ipv6Setting.setPrivacy(static_cast(m_ui->privacyCombo->currentIndex() - 1)); } return ipv6Setting.toMap(); } void IPv6Widget::slotModeComboChanged(int index) { if (index == Automatic) { // Automatic m_ui->dnsLabel->setText(i18n("Other DNS Servers:")); m_ui->dns->setEnabled(true); m_ui->dnsMorePushButton->setEnabled(true); m_ui->dnsSearch->setEnabled(true); m_ui->dnsSearchMorePushButton->setEnabled(true); m_ui->ipv6RequiredCB->setEnabled(true); m_ui->privacyCombo->setEnabled(true); m_ui->btnRoutes->setEnabled(true); m_ui->tableViewAddresses->setEnabled(false); m_ui->btnAdd->setEnabled(false); m_ui->btnRemove->setEnabled(false); } else if (index == AutomaticOnlyIP) { m_ui->dnsLabel->setText(i18n("DNS Servers:")); m_ui->dns->setEnabled(true); m_ui->dnsMorePushButton->setEnabled(true); m_ui->dnsSearch->setEnabled(true); m_ui->dnsSearchMorePushButton->setEnabled(true); m_ui->ipv6RequiredCB->setEnabled(true); m_ui->privacyCombo->setEnabled(true); m_ui->btnRoutes->setEnabled(true); m_ui->tableViewAddresses->setEnabled(false); m_ui->btnAdd->setEnabled(false); m_ui->btnRemove->setEnabled(false); } else if (index == Manual) { // Manual m_ui->dnsLabel->setText(i18n("DNS Servers:")); m_ui->dns->setEnabled(true); m_ui->dnsMorePushButton->setEnabled(true); m_ui->dnsSearch->setEnabled(true); m_ui->dnsSearchMorePushButton->setEnabled(true); m_ui->ipv6RequiredCB->setEnabled(true); m_ui->privacyCombo->setEnabled(true); m_ui->btnRoutes->setEnabled(true); m_ui->tableViewAddresses->setEnabled(true); m_ui->btnAdd->setEnabled(true); m_ui->btnRemove->setEnabled(true); } else if (index == AutomaticOnlyDHCP || index == LinkLocal) { // Link-local or DHCP m_ui->dnsLabel->setText(i18n("DNS Servers:")); m_ui->dns->setEnabled(false); m_ui->dnsMorePushButton->setEnabled(false); m_ui->dnsSearch->setEnabled(false); m_ui->dnsSearchMorePushButton->setEnabled(false); m_ui->ipv6RequiredCB->setEnabled(true); m_ui->privacyCombo->setEnabled(true); m_ui->btnRoutes->setEnabled(false); m_ui->tableViewAddresses->setEnabled(false); m_ui->btnAdd->setEnabled(false); m_ui->btnRemove->setEnabled(false); } else if (index == Disabled) { // Ignored m_ui->dnsLabel->setText(i18n("DNS Servers:")); m_ui->dns->setEnabled(false); m_ui->dnsMorePushButton->setEnabled(false); m_ui->dnsSearch->setEnabled(false); m_ui->dnsSearchMorePushButton->setEnabled(false); m_ui->ipv6RequiredCB->setEnabled(false); m_ui->privacyCombo->setEnabled(false); m_ui->btnRoutes->setEnabled(false); m_ui->tableViewAddresses->setEnabled(false); m_ui->btnAdd->setEnabled(false); m_ui->btnRemove->setEnabled(false); } } void IPv6Widget::slotAddIPAddress() { QList item; item << new QStandardItem << new QStandardItem << new QStandardItem; d->model.appendRow(item); const int rowCount = d->model.rowCount(); if (rowCount > 0) { m_ui->tableViewAddresses->selectRow(rowCount - 1); QItemSelectionModel * selectionModel = m_ui->tableViewAddresses->selectionModel(); QModelIndexList list = selectionModel->selectedIndexes(); if (list.size()) { // QTableView is configured to select only rows. // So, list[0] - IP address. m_ui->tableViewAddresses->edit(list[0]); } } } void IPv6Widget::slotRemoveIPAddress() { QItemSelectionModel * selectionModel = m_ui->tableViewAddresses->selectionModel(); if (selectionModel->hasSelection()) { QModelIndexList indexes = selectionModel->selectedIndexes(); d->model.takeRow(indexes[0].row()); } m_ui->btnRemove->setEnabled(m_ui->tableViewAddresses->selectionModel()->hasSelection()); } void IPv6Widget::selectionChanged(const QItemSelection & selected) { m_ui->btnRemove->setEnabled(!selected.isEmpty()); } void IPv6Widget::tableViewItemChanged(QStandardItem *item) { if (item->text().isEmpty()) { return; } const int column = item->column(); if (column == 0) { // ip int row = item->row(); QStandardItem *netmaskItem = d->model.item(row, column + 1); // netmask if (netmaskItem && netmaskItem->text().isEmpty()) { QHostAddress addr(item->text()); const quint32 netmask = suggestNetmask(addr.toIPv6Address()); if (netmask) { netmaskItem->setText(QString::number(netmask,10)); } } } } void IPv6Widget::slotRoutesDialog() { QPointer dlg = new IpV6RoutesWidget(this); dlg->setRoutes(m_tmpIpv6Setting.routes()); dlg->setNeverDefault(m_tmpIpv6Setting.neverDefault()); if (m_ui->method->currentIndex() == 3) { // manual dlg->setIgnoreAutoRoutesCheckboxEnabled(false); } else { dlg->setIgnoreAutoRoutes(m_tmpIpv6Setting.ignoreAutoRoutes()); } connect(dlg.data(), &QDialog::accepted, [dlg, this] () { m_tmpIpv6Setting.setRoutes(dlg->routes()); m_tmpIpv6Setting.setNeverDefault(dlg->neverDefault()); m_tmpIpv6Setting.setIgnoreAutoRoutes(dlg->ignoreautoroutes()); }); connect(dlg.data(), &QDialog::finished, [dlg] () { if (dlg) { dlg->deleteLater(); } }); dlg->setModal(true); dlg->show(); } void IPv6Widget::slotDnsServers() { QPointer dialog = new QDialog(this); dialog->setWindowTitle(i18n("Edit DNS servers")); dialog->setLayout(new QVBoxLayout); 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); KEditListWidget * listWidget = new KEditListWidget(dialog); listWidget->setItems(m_ui->dns->text().split(',').replaceInStrings(" ", "")); listWidget->lineEdit()->setFocus(Qt::OtherFocusReason); dialog->layout()->addWidget(listWidget); dialog->layout()->addWidget(buttons); connect(dialog.data(), &QDialog::accepted, [listWidget, this] () { QString text = listWidget->items().join(","); if (text.endsWith(',')) { text.chop(1); } m_ui->dns->setText(text); }); connect(dialog.data(), &QDialog::finished, [dialog] () { if (dialog) { dialog->deleteLater(); } }); dialog->setModal(true); dialog->show(); } void IPv6Widget::slotDnsDomains() { QPointer dialog = new QDialog(this); dialog->setWindowTitle(i18n("Edit DNS search domains")); dialog->setLayout(new QVBoxLayout); 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); KEditListWidget * listWidget = new KEditListWidget(dialog); listWidget->setItems(m_ui->dnsSearch->text().split(',').replaceInStrings(" ", "")); listWidget->lineEdit()->setFocus(Qt::OtherFocusReason); dialog->layout()->addWidget(listWidget); dialog->layout()->addWidget(buttons); connect(dialog.data(), &QDialog::accepted, [listWidget, this] () { QString text = listWidget->items().join(","); if (text.endsWith(',')) { text.chop(1); } m_ui->dnsSearch->setText(text); }); connect(dialog.data(), &QDialog::finished, [dialog] () { if (dialog) { dialog->deleteLater(); } }); dialog->setModal(true); dialog->show(); } bool IPv6Widget::isValid() const { if (m_ui->method->currentIndex() == Manual) { if (!d->model.rowCount()) { return false; } for (int i = 0, rowCount = d->model.rowCount(); i < rowCount; i++) { QHostAddress ip = QHostAddress(d->model.item(i, 0)->text()); const int prefix = d->model.item(i,1)->text().toInt(); QHostAddress gateway = QHostAddress(d->model.item(i, 2)->text()); if (ip.isNull() || !(prefix >= 1 && prefix <= 128) || (gateway.isNull() && !d->model.item(i, 2)->text().isEmpty())) { return false; } } } if (!m_ui->dns->text().isEmpty() && (m_ui->method->currentIndex() == Automatic || m_ui->method->currentIndex() == Manual || m_ui->method->currentIndex() == AutomaticOnlyIP)) { const QStringList tmp = m_ui->dns->text().split(','); for (const QString &str : tmp) { QHostAddress addr(str); if (addr.isNull()) { return false; } } } return true; } diff --git a/libs/editor/settings/security802-1x.cpp b/libs/editor/settings/security802-1x.cpp index de5a6a64..3a2f0d0d 100644 --- a/libs/editor/settings/security802-1x.cpp +++ b/libs/editor/settings/security802-1x.cpp @@ -1,638 +1,642 @@ /* Copyright (c) 2013 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "security802-1x.h" #include "ui_802-1x.h" #include "editlistdialog.h" #include "listvalidator.h" #include #include #include Security8021x::Security8021x(const NetworkManager::Setting::Ptr &setting, bool wifiMode, QWidget *parent, Qt::WindowFlags f) : SettingWidget(setting, parent, f) , m_ui(new Ui::Security8021x) { m_setting = setting.staticCast(); m_ui->setupUi(this); m_ui->fastPassword->setPasswordOptionsEnabled(true); m_ui->leapPassword->setPasswordOptionsEnabled(true); m_ui->md5Password->setPasswordOptionsEnabled(true); m_ui->peapPassword->setPasswordOptionsEnabled(true); m_ui->pwdPassword->setPasswordOptionsEnabled(true); m_ui->tlsPrivateKeyPassword->setPasswordOptionsEnabled(true); m_ui->ttlsPassword->setPasswordOptionsEnabled(true); if (wifiMode) { m_ui->auth->removeItem(0); // MD 5 m_ui->stackedWidget->removeWidget(m_ui->md5Page); m_ui->auth->setItemData(0, NetworkManager::Security8021xSetting::EapMethodTls); m_ui->auth->setItemData(1, NetworkManager::Security8021xSetting::EapMethodLeap); m_ui->auth->setItemData(2, NetworkManager::Security8021xSetting::EapMethodPwd); m_ui->auth->setItemData(3, NetworkManager::Security8021xSetting::EapMethodFast); m_ui->auth->setItemData(4, NetworkManager::Security8021xSetting::EapMethodTtls); m_ui->auth->setItemData(5, NetworkManager::Security8021xSetting::EapMethodPeap); } else { m_ui->auth->removeItem(2); // LEAP m_ui->stackedWidget->removeWidget(m_ui->leapPage); m_ui->auth->setItemData(0, NetworkManager::Security8021xSetting::EapMethodMd5); m_ui->auth->setItemData(1, NetworkManager::Security8021xSetting::EapMethodTls); m_ui->auth->setItemData(2, NetworkManager::Security8021xSetting::EapMethodPwd); m_ui->auth->setItemData(3, NetworkManager::Security8021xSetting::EapMethodFast); m_ui->auth->setItemData(4, NetworkManager::Security8021xSetting::EapMethodTtls); m_ui->auth->setItemData(5, NetworkManager::Security8021xSetting::EapMethodPeap); } // Set PEAP authentication as default m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodPeap)); connect(m_ui->btnTlsAltSubjectMatches, &QPushButton::clicked, this, &Security8021x::altSubjectMatchesButtonClicked); connect(m_ui->btnTlsConnectToServers, &QPushButton::clicked, this, &Security8021x::connectToServersButtonClicked); // Connect for setting check watchChangedSetting(); // Connect for validity check +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->auth, QOverload::of(&KComboBox::currentIndexChanged), this, &Security8021x::slotWidgetChanged); +#else + connect(m_ui->auth, QOverload::of(&KComboBox::currentIndexChanged), this, &Security8021x::slotWidgetChanged); +#endif connect(m_ui->md5UserName, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->md5Password, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->md5Password, &PasswordField::passwordOptionChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->tlsIdentity, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->tlsCACert, &KUrlRequester::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->tlsUserCert, &KUrlRequester::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->tlsPrivateKey, &KUrlRequester::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->tlsPrivateKeyPassword, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->tlsPrivateKeyPassword, &PasswordField::passwordOptionChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->leapUsername, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->leapPassword, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->leapPassword, &PasswordField::passwordOptionChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->fastAllowPacProvisioning, &QCheckBox::stateChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->pacFile, &KUrlRequester::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->pwdUsername, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->pwdPassword, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->fastUsername, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->fastPassword, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->fastPassword, &PasswordField::passwordOptionChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->ttlsCACert, &KUrlRequester::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->ttlsUsername, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->ttlsPassword, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->ttlsPassword, &PasswordField::passwordOptionChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->peapCACert, &KUrlRequester::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->peapUsername, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->peapPassword, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged); connect(m_ui->peapPassword, &PasswordField::passwordOptionChanged, this, &Security8021x::slotWidgetChanged); KAcceleratorManager::manage(this); connect(m_ui->stackedWidget, &QStackedWidget::currentChanged, this, &Security8021x::currentAuthChanged); altSubjectValidator = new QRegExpValidator(QRegExp(QLatin1String("^(DNS:[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_.-]+|EMAIL:[a-zA-Z0-9._-]+@[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_.-]+|URI:[a-zA-Z0-9.+-]+:.+|)$")), this); serversValidator = new QRegExpValidator(QRegExp(QLatin1String("^[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_.-]+$")), this); ListValidator *altSubjectListValidator = new ListValidator(this); altSubjectListValidator->setInnerValidator(altSubjectValidator); m_ui->leTlsSubjectMatch->setValidator(altSubjectListValidator); ListValidator *serverListValidator = new ListValidator(this); serverListValidator->setInnerValidator(serversValidator); m_ui->leTlsConnectToServers->setValidator(serverListValidator); if (setting) { loadConfig(setting); } } Security8021x::~Security8021x() { delete m_ui; } void Security8021x::loadConfig(const NetworkManager::Setting::Ptr &setting) { NetworkManager::Security8021xSetting::Ptr securitySetting = setting.staticCast(); const QList eapMethods = securitySetting->eapMethods(); const NetworkManager::Security8021xSetting::AuthMethod phase2AuthMethod = securitySetting->phase2AuthMethod(); if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodMd5)) { m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodMd5)); m_ui->md5UserName->setText(securitySetting->identity()); if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::None)) { m_ui->md5Password->setPasswordOption(PasswordField::StoreForAllUsers); } else if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::AgentOwned)) { m_ui->md5Password->setPasswordOption(PasswordField::StoreForUser); } else { m_ui->md5Password->setPasswordOption(PasswordField::AlwaysAsk); } } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodTls)) { QStringList servers; m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodTls)); m_ui->tlsIdentity->setText(securitySetting->identity()); m_ui->tlsDomain->setText(securitySetting->domainSuffixMatch()); m_ui->tlsUserCert->setUrl(QUrl::fromLocalFile(securitySetting->clientCertificate())); m_ui->tlsCACert->setUrl(QUrl::fromLocalFile(securitySetting->caCertificate())); m_ui->leTlsSubjectMatch->setText(securitySetting->subjectMatch()); m_ui->leTlsAlternativeSubjectMatches->setText(securitySetting->altSubjectMatches().join(QLatin1String(", "))); for (const QString &match : securitySetting->altSubjectMatches()) { if (match.startsWith(QLatin1String("DNS:"))) { servers.append(match.right(match.length()-4)); } } m_ui->leTlsConnectToServers->setText(servers.join(QLatin1String(", "))); m_ui->tlsPrivateKey->setUrl(QUrl::fromLocalFile(securitySetting->privateKey())); if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::None)) { m_ui->tlsPrivateKeyPassword->setPasswordOption(PasswordField::StoreForAllUsers); } else if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::AgentOwned)) { m_ui->tlsPrivateKeyPassword->setPasswordOption(PasswordField::StoreForUser); } else { m_ui->tlsPrivateKeyPassword->setPasswordOption(PasswordField::AlwaysAsk); } } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodLeap)) { m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodLeap)); m_ui->leapUsername->setText(securitySetting->identity()); if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::None)) { m_ui->leapPassword->setPasswordOption(PasswordField::StoreForAllUsers); } else if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::AgentOwned)) { m_ui->leapPassword->setPasswordOption(PasswordField::StoreForUser); } else { m_ui->leapPassword->setPasswordOption(PasswordField::AlwaysAsk); } } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodPwd)) { m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodPwd)); m_ui->pwdUsername->setText(securitySetting->identity()); if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::None)) { m_ui->pwdPassword->setPasswordOption(PasswordField::StoreForAllUsers); } else if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::AgentOwned)) { m_ui->pwdPassword->setPasswordOption(PasswordField::StoreForUser); } else { m_ui->pwdPassword->setPasswordOption(PasswordField::AlwaysAsk); } } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodFast)) { m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodFast)); m_ui->fastAnonIdentity->setText(securitySetting->anonymousIdentity()); m_ui->fastAllowPacProvisioning->setChecked((int)securitySetting->phase1FastProvisioning() > 0); m_ui->pacMethod->setCurrentIndex(securitySetting->phase1FastProvisioning() - 1); m_ui->pacFile->setUrl(QUrl::fromLocalFile(securitySetting->pacFile())); if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodGtc) { m_ui->fastInnerAuth->setCurrentIndex(0); } else { m_ui->fastInnerAuth->setCurrentIndex(1); } m_ui->fastUsername->setText(securitySetting->identity()); if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::None)) { m_ui->fastPassword->setPasswordOption(PasswordField::StoreForAllUsers); } else if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::AgentOwned)) { m_ui->fastPassword->setPasswordOption(PasswordField::StoreForUser); } else { m_ui->fastPassword->setPasswordOption(PasswordField::AlwaysAsk); } } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodTtls)) { m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodTtls)); m_ui->ttlsAnonIdentity->setText(securitySetting->anonymousIdentity()); m_ui->ttlsDomain->setText(securitySetting->domainSuffixMatch()); m_ui->ttlsCACert->setUrl(QUrl::fromLocalFile(securitySetting->caCertificate())); if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodPap) { m_ui->ttlsInnerAuth->setCurrentIndex(0); } else if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodMschap) { m_ui->ttlsInnerAuth->setCurrentIndex(1); } else if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodMschapv2) { m_ui->ttlsInnerAuth->setCurrentIndex(2); } else if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodChap) { m_ui->ttlsInnerAuth->setCurrentIndex(3); } m_ui->ttlsUsername->setText(securitySetting->identity()); if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::None)) { m_ui->ttlsPassword->setPasswordOption(PasswordField::StoreForAllUsers); } else if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::AgentOwned)) { m_ui->ttlsPassword->setPasswordOption(PasswordField::StoreForUser); } else { m_ui->ttlsPassword->setPasswordOption(PasswordField::AlwaysAsk); } } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodPeap)) { m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodPeap)); m_ui->peapAnonIdentity->setText(securitySetting->anonymousIdentity()); m_ui->peapDomain->setText(securitySetting->domainSuffixMatch()); m_ui->peapCACert->setUrl(QUrl::fromLocalFile(securitySetting->caCertificate())); m_ui->peapVersion->setCurrentIndex(securitySetting->phase1PeapVersion() + 1); if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodMschapv2) { m_ui->peapInnerAuth->setCurrentIndex(0); } else if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodMd5) { m_ui->peapInnerAuth->setCurrentIndex(1); } else if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodGtc) { m_ui->peapInnerAuth->setCurrentIndex(2); } m_ui->peapUsername->setText(securitySetting->identity()); if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::None)) { m_ui->peapPassword->setPasswordOption(PasswordField::StoreForAllUsers); } else if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::AgentOwned)) { m_ui->peapPassword->setPasswordOption(PasswordField::StoreForUser); } else { m_ui->peapPassword->setPasswordOption(PasswordField::AlwaysAsk); } } loadSecrets(setting); } void Security8021x::loadSecrets(const NetworkManager::Setting::Ptr &setting) { NetworkManager::Security8021xSetting::Ptr securitySetting = setting.staticCast(); const QString password = securitySetting->password(); const QList eapMethods = securitySetting->eapMethods(); if (!password.isEmpty()) { if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodMd5)) { m_ui->md5Password->setText(securitySetting->password()); } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodLeap)) { m_ui->leapPassword->setText(securitySetting->password()); } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodFast)) { m_ui->fastPassword->setText(securitySetting->password()); } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodPwd)) { m_ui->pwdPassword->setText(securitySetting->password()); } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodTtls)) { m_ui->ttlsPassword->setText(securitySetting->password()); } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodPeap)) { m_ui->peapPassword->setText(securitySetting->password()); } } if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodTls)) { const QString privateKeyPassword = securitySetting->privateKeyPassword(); if (!privateKeyPassword.isEmpty()) { m_ui->tlsPrivateKeyPassword->setText(securitySetting->privateKeyPassword()); } } } QVariantMap Security8021x::setting() const { NetworkManager::Security8021xSetting setting; NetworkManager::Security8021xSetting::EapMethod method = static_cast(m_ui->auth->itemData(m_ui->auth->currentIndex()).toInt()); setting.setEapMethods(QList() << method); if (method == NetworkManager::Security8021xSetting::EapMethodMd5) { if (!m_ui->md5UserName->text().isEmpty()) { setting.setIdentity(m_ui->md5UserName->text()); } if (m_ui->md5Password->passwordOption() == PasswordField::StoreForAllUsers) { setting.setPasswordFlags(NetworkManager::Setting::None); } else if (m_ui->md5Password->passwordOption() == PasswordField::StoreForUser) { setting.setPasswordFlags(NetworkManager::Setting::AgentOwned); } else { setting.setPasswordFlags(NetworkManager::Setting::NotSaved); } if (!m_ui->md5Password->text().isEmpty()) { setting.setPassword(m_ui->md5Password->text()); } } else if (method == NetworkManager::Security8021xSetting::EapMethodTls) { if (!m_ui->tlsIdentity->text().isEmpty()) { setting.setIdentity(m_ui->tlsIdentity->text()); } if (!m_ui->tlsDomain->text().isEmpty()) { setting.setDomainSuffixMatch(m_ui->tlsDomain->text()); } if (m_ui->tlsUserCert->url().isValid()) { setting.setClientCertificate(m_ui->tlsUserCert->url().toString().toUtf8().append('\0')); } if (m_ui->tlsCACert->url().isValid()) { setting.setCaCertificate(m_ui->tlsCACert->url().toString().toUtf8().append('\0')); } QStringList altsubjectmatches = m_ui->leTlsAlternativeSubjectMatches->text().remove(QLatin1Char(' ')).split(QLatin1Char(','), QString::SkipEmptyParts); for (const QString &match : m_ui->leTlsConnectToServers->text().remove(QLatin1Char(' ')).split(QLatin1Char(','), QString::SkipEmptyParts)) { const QString tempstr = QLatin1String("DNS:") + match; if (!altsubjectmatches.contains(tempstr)) { altsubjectmatches.append(tempstr); } } setting.setSubjectMatch(m_ui->leTlsSubjectMatch->text()); setting.setAltSubjectMatches(altsubjectmatches); if (m_ui->tlsPrivateKey->url().isValid()) { setting.setPrivateKey(m_ui->tlsPrivateKey->url().toString().toUtf8().append('\0')); } if (!m_ui->tlsPrivateKeyPassword->text().isEmpty()) { setting.setPrivateKeyPassword(m_ui->tlsPrivateKeyPassword->text()); } QCA::Initializer init; QCA::ConvertResult convRes; // Try if the private key is in pkcs12 format bundled with client certificate if (QCA::isSupported("pkcs12")) { QCA::KeyBundle keyBundle = QCA::KeyBundle::fromFile(m_ui->tlsPrivateKey->url().path(), m_ui->tlsPrivateKeyPassword->text().toUtf8(), &convRes); // Set client certificate to the same path as private key if (convRes == QCA::ConvertGood && keyBundle.privateKey().canDecrypt()) { setting.setClientCertificate(m_ui->tlsPrivateKey->url().toString().toUtf8().append('\0')); } } if (m_ui->tlsPrivateKeyPassword->passwordOption() == PasswordField::StoreForAllUsers) { setting.setPrivateKeyPasswordFlags(NetworkManager::Setting::None); } else if (m_ui->tlsPrivateKeyPassword->passwordOption() == PasswordField::StoreForUser) { setting.setPrivateKeyPasswordFlags(NetworkManager::Setting::AgentOwned); } else { setting.setPrivateKeyPasswordFlags(NetworkManager::Setting::NotSaved); } } else if (method == NetworkManager::Security8021xSetting::EapMethodLeap) { if (!m_ui->leapUsername->text().isEmpty()) { setting.setIdentity(m_ui->leapUsername->text()); } if (!m_ui->leapPassword->text().isEmpty()) { setting.setPassword(m_ui->leapPassword->text()); } if (m_ui->leapPassword->passwordOption() == PasswordField::StoreForAllUsers) { setting.setPasswordFlags(NetworkManager::Setting::None); } else if (m_ui->leapPassword->passwordOption() == PasswordField::StoreForUser) { setting.setPasswordFlags(NetworkManager::Setting::AgentOwned); } else { setting.setPasswordFlags(NetworkManager::Setting::NotSaved); } } else if (method == NetworkManager::Security8021xSetting::EapMethodPwd) { if (!m_ui->pwdUsername->text().isEmpty()) { setting.setIdentity(m_ui->pwdUsername->text()); } if (m_ui->pwdPassword->passwordOption() == PasswordField::StoreForAllUsers) { setting.setPasswordFlags(NetworkManager::Setting::None); } else if (m_ui->pwdPassword->passwordOption() == PasswordField::StoreForUser) { setting.setPasswordFlags(NetworkManager::Setting::AgentOwned); } else { setting.setPasswordFlags(NetworkManager::Setting::NotSaved); } if (!m_ui->pwdPassword->text().isEmpty()) { setting.setPassword(m_ui->pwdPassword->text()); } } else if (method == NetworkManager::Security8021xSetting::EapMethodFast) { if (!m_ui->fastAnonIdentity->text().isEmpty()) { setting.setAnonymousIdentity(m_ui->fastAnonIdentity->text()); } if (!m_ui->fastAllowPacProvisioning->isChecked()) { setting.setPhase1FastProvisioning(NetworkManager::Security8021xSetting::FastProvisioningDisabled); } else { setting.setPhase1FastProvisioning(static_cast(m_ui->pacMethod->currentIndex() + 1)); } if (m_ui->pacFile->url().isValid()) { setting.setPacFile(QFile::encodeName(m_ui->pacFile->url().toLocalFile())); } if (m_ui->fastInnerAuth->currentIndex() == 0) { setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodGtc); } else { setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodMschapv2); } if (!m_ui->fastUsername->text().isEmpty()) { setting.setIdentity(m_ui->fastUsername->text()); } if (!m_ui->fastPassword->text().isEmpty()) { setting.setPassword(m_ui->fastPassword->text()); } if (m_ui->fastPassword->passwordOption() == PasswordField::StoreForAllUsers) { setting.setPasswordFlags(NetworkManager::Setting::None); } else if (m_ui->fastPassword->passwordOption() == PasswordField::StoreForUser) { setting.setPasswordFlags(NetworkManager::Setting::AgentOwned); } else { setting.setPasswordFlags(NetworkManager::Setting::NotSaved); } } else if (method == NetworkManager::Security8021xSetting::EapMethodTtls) { if (!m_ui->ttlsAnonIdentity->text().isEmpty()) { setting.setAnonymousIdentity(m_ui->ttlsAnonIdentity->text()); } if (!m_ui->ttlsDomain->text().isEmpty()) { setting.setDomainSuffixMatch(m_ui->ttlsDomain->text()); } if (m_ui->ttlsCACert->url().isValid()) { setting.setCaCertificate(m_ui->ttlsCACert->url().toString().toUtf8().append('\0')); } const int innerAuth = m_ui->ttlsInnerAuth->currentIndex(); if (innerAuth == 0) { setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodPap); } else if (innerAuth == 1) { setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodMschap); } else if (innerAuth == 2) { setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodMschapv2); } else if (innerAuth == 3) { setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodChap); } if (!m_ui->ttlsUsername->text().isEmpty()) { setting.setIdentity(m_ui->ttlsUsername->text()); } if (!m_ui->ttlsPassword->text().isEmpty()) { setting.setPassword(m_ui->ttlsPassword->text()); } if (m_ui->ttlsPassword->passwordOption() == PasswordField::StoreForAllUsers) { setting.setPasswordFlags(NetworkManager::Setting::None); } else if (m_ui->ttlsPassword->passwordOption() == PasswordField::StoreForUser) { setting.setPasswordFlags(NetworkManager::Setting::AgentOwned); } else { setting.setPasswordFlags(NetworkManager::Setting::NotSaved); } } else if (method == NetworkManager::Security8021xSetting::EapMethodPeap) { if (!m_ui->peapAnonIdentity->text().isEmpty()) { setting.setAnonymousIdentity(m_ui->peapAnonIdentity->text()); } if (!m_ui->peapDomain->text().isEmpty()) { setting.setDomainSuffixMatch(m_ui->peapDomain->text()); } if (m_ui->peapCACert->url().isValid()) { setting.setCaCertificate(m_ui->peapCACert->url().toString().toUtf8().append('\0')); } setting.setPhase1PeapVersion(static_cast(m_ui->peapVersion->currentIndex() - 1)); const int innerAuth = m_ui->peapInnerAuth->currentIndex(); if (innerAuth == 0) { setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodMschapv2); } else if (innerAuth == 1) { setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodMd5); } else if (innerAuth == 2) { setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodGtc); } if (!m_ui->peapUsername->text().isEmpty()) { setting.setIdentity(m_ui->peapUsername->text()); } if (!m_ui->peapPassword->text().isEmpty()) { setting.setPassword(m_ui->peapPassword->text()); } if (m_ui->peapPassword->passwordOption() == PasswordField::StoreForAllUsers) { setting.setPasswordFlags(NetworkManager::Setting::None); } else if (m_ui->peapPassword->passwordOption() == PasswordField::StoreForUser) { setting.setPasswordFlags(NetworkManager::Setting::AgentOwned); } else { setting.setPasswordFlags(NetworkManager::Setting::NotSaved); } } return setting.toMap(); } void Security8021x::altSubjectMatchesButtonClicked() { QPointer editor = new EditListDialog(this); editor->setItems(m_ui->leTlsSubjectMatch->text().remove(QLatin1Char(' ')).split(QLatin1Char(','), QString::SkipEmptyParts)); editor->setWindowTitle(i18n("Alternative Subject Matches")); editor->setToolTip(i18n("This entry must be one of:
  • DNS: <name or ip address>
  • EMAIL: <email>
  • URI: <uri, e.g. https://www.kde.org>
")); editor->setValidator(altSubjectValidator); connect(editor.data(), &QDialog::accepted, [editor, this] () { m_ui->leTlsSubjectMatch->setText(editor->items().join(QLatin1String(", "))); }); connect(editor.data(), &QDialog::finished, [editor] () { if (editor) { editor->deleteLater(); } }); editor->setModal(true); editor->show(); } void Security8021x::connectToServersButtonClicked() { QPointer editor = new EditListDialog(this); editor->setItems(m_ui->leTlsConnectToServers->text().remove(QLatin1Char(' ')).split(QLatin1Char(','), QString::SkipEmptyParts)); editor->setWindowTitle(i18n("Connect to these servers only")); editor->setValidator(serversValidator); connect(editor.data(), &QDialog::accepted, [editor, this] () { m_ui->leTlsConnectToServers->setText(editor->items().join(QLatin1String(", "))); }); connect(editor.data(), &QDialog::finished, [editor] () { if (editor) { editor->deleteLater(); } }); editor->setModal(true); editor->show(); } bool Security8021x::isValid() const { NetworkManager::Security8021xSetting::EapMethod method = static_cast(m_ui->auth->itemData(m_ui->auth->currentIndex()).toInt()); if (method == NetworkManager::Security8021xSetting::EapMethodMd5) { return !m_ui->md5UserName->text().isEmpty() && (!m_ui->md5Password->text().isEmpty() || m_ui->md5Password->passwordOption() == PasswordField::AlwaysAsk); } else if (method == NetworkManager::Security8021xSetting::EapMethodTls) { if (m_ui->tlsIdentity->text().isEmpty()) { return false; } if (!m_ui->tlsPrivateKey->url().isValid()) { return false; } if (m_ui->tlsPrivateKeyPassword->passwordOption() == PasswordField::AlwaysAsk) { return true; } if (m_ui->tlsPrivateKeyPassword->text().isEmpty()) { return false; } QCA::Initializer init; QCA::ConvertResult convRes; // Try if the private key is in pkcs12 format bundled with client certificate if (QCA::isSupported("pkcs12")) { QCA::KeyBundle keyBundle = QCA::KeyBundle::fromFile(m_ui->tlsPrivateKey->url().path(), m_ui->tlsPrivateKeyPassword->text().toUtf8(), &convRes); // We can return the result of decryption when we managed to import the private key if (convRes == QCA::ConvertGood) { return keyBundle.privateKey().canDecrypt(); } } // If the private key is not in pkcs12 format, we need client certificate to be set if (!m_ui->tlsUserCert->url().isValid()) { return false; } // Try if the private key is in PEM format and return the result of decryption if we managed to open it QCA::PrivateKey key = QCA::PrivateKey::fromPEMFile(m_ui->tlsPrivateKey->url().path(), m_ui->tlsPrivateKeyPassword->text().toUtf8(), &convRes); if (convRes == QCA::ConvertGood) { return key.canDecrypt(); } // TODO Try other formats (DER - mainly used in Windows) // TODO Validate other certificates?? } else if (method == NetworkManager::Security8021xSetting::EapMethodLeap) { return !m_ui->leapUsername->text().isEmpty() && (!m_ui->leapPassword->text().isEmpty() || m_ui->leapPassword->passwordOption() == PasswordField::AlwaysAsk); } else if (method == NetworkManager::Security8021xSetting::EapMethodPwd) { return !m_ui->pwdUsername->text().isEmpty() && (!m_ui->pwdPassword->text().isEmpty() || m_ui->pwdPassword->passwordOption() == PasswordField::AlwaysAsk); } else if (method == NetworkManager::Security8021xSetting::EapMethodFast) { if (!m_ui->fastAllowPacProvisioning->isChecked() && !m_ui->pacFile->url().isValid()) { return false; } return !m_ui->fastUsername->text().isEmpty() && (!m_ui->fastPassword->text().isEmpty() || m_ui->fastPassword->passwordOption() == PasswordField::AlwaysAsk); } else if (method == NetworkManager::Security8021xSetting::EapMethodTtls) { return !m_ui->ttlsUsername->text().isEmpty() && (!m_ui->ttlsPassword->text().isEmpty() || m_ui->ttlsPassword->passwordOption() == PasswordField::AlwaysAsk); } else if (method == NetworkManager::Security8021xSetting::EapMethodPeap) { return !m_ui->peapUsername->text().isEmpty() && (!m_ui->peapPassword->text().isEmpty() || m_ui->peapPassword->passwordOption() == PasswordField::AlwaysAsk); } return true; } void Security8021x::currentAuthChanged(int index) { Q_UNUSED(index); KAcceleratorManager::manage(m_ui->stackedWidget->currentWidget()); } diff --git a/libs/editor/settings/vlanwidget.cpp b/libs/editor/settings/vlanwidget.cpp index fddea2c4..57aff392 100644 --- a/libs/editor/settings/vlanwidget.cpp +++ b/libs/editor/settings/vlanwidget.cpp @@ -1,106 +1,110 @@ /* Copyright 2013 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "vlanwidget.h" #include "ui_vlan.h" #include "uiutils.h" #include #include VlanWidget::VlanWidget(const NetworkManager::Setting::Ptr &setting, QWidget* parent, Qt::WindowFlags f): SettingWidget(setting, parent, f), m_ui(new Ui::VlanWidget) { m_ui->setupUi(this); fillConnections(); connect(m_ui->ifaceName, &KLineEdit::textChanged, this, &VlanWidget::slotWidgetChanged); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->parent, QOverload::of(&KComboBox::currentIndexChanged), this, &VlanWidget::slotWidgetChanged); +#else + connect(m_ui->parent, QOverload::of(&KComboBox::currentIndexChanged), this, &VlanWidget::slotWidgetChanged); +#endif connect(m_ui->parent->lineEdit(), &QLineEdit::textChanged, this, &VlanWidget::slotWidgetChanged); // Connect for setting check watchChangedSetting(); KAcceleratorManager::manage(this); if (setting) { loadConfig(setting); } } VlanWidget::~VlanWidget() { delete m_ui; } void VlanWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { NetworkManager::VlanSetting::Ptr vlanSetting = setting.staticCast(); m_ui->parent->setCurrentIndex(m_ui->parent->findData(vlanSetting->parent())); m_ui->id->setValue(vlanSetting->id()); m_ui->ifaceName->setText(vlanSetting->interfaceName()); m_ui->reorderHeaders->setChecked(vlanSetting->flags().testFlag(NetworkManager::VlanSetting::ReorderHeaders)); m_ui->gvrp->setChecked(vlanSetting->flags().testFlag(NetworkManager::VlanSetting::Gvrp)); m_ui->looseBinding->setChecked(vlanSetting->flags().testFlag(NetworkManager::VlanSetting::LooseBinding)); } QVariantMap VlanWidget::setting() const { NetworkManager::VlanSetting setting; setting.setParent(m_ui->parent->itemData(m_ui->parent->currentIndex()).toString()); setting.setId(m_ui->id->value()); const QString ifaceName = m_ui->ifaceName->text(); if (!ifaceName.isEmpty()) setting.setInterfaceName(ifaceName); NetworkManager::VlanSetting::Flags flags; if (m_ui->reorderHeaders->isChecked()) flags |= NetworkManager::VlanSetting::ReorderHeaders; if (m_ui->gvrp->isChecked()) flags |= NetworkManager::VlanSetting::Gvrp; if (m_ui->looseBinding->isChecked()) flags |= NetworkManager::VlanSetting::LooseBinding; if (flags) setting.setFlags(flags); return setting.toMap(); } void VlanWidget::fillConnections() { m_ui->parent->clear(); for (const NetworkManager::Connection::Ptr &con : NetworkManager::listConnections()) { if (!con->settings()->isSlave() && con->settings()->connectionType() == NetworkManager::ConnectionSettings::Wired) m_ui->parent->addItem(con->name(), con->uuid()); } } bool VlanWidget::isValid() const { return !m_ui->parent->currentText().isEmpty() || !m_ui->ifaceName->text().isEmpty(); } diff --git a/libs/editor/settings/wificonnectionwidget.cpp b/libs/editor/settings/wificonnectionwidget.cpp index 48ced259..edb0981c 100644 --- a/libs/editor/settings/wificonnectionwidget.cpp +++ b/libs/editor/settings/wificonnectionwidget.cpp @@ -1,204 +1,212 @@ /* Copyright (c) 2013 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "debug.h" #include "wificonnectionwidget.h" #include "ui_wificonnectionwidget.h" #include #include #include #include "uiutils.h" WifiConnectionWidget::WifiConnectionWidget(const NetworkManager::Setting::Ptr &setting, QWidget* parent, Qt::WindowFlags f): SettingWidget(setting, parent, f), m_ui(new Ui::WifiConnectionWidget) { m_ui->setupUi(this); connect(m_ui->btnRandomMacAddr, &QPushButton::clicked, this, &WifiConnectionWidget::generateRandomClonedMac); connect(m_ui->SSIDCombo, &SsidComboBox::ssidChanged, this, QOverload<>::of(&WifiConnectionWidget::ssidChanged)); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->modeComboBox, QOverload::of(&KComboBox::currentIndexChanged), this, &WifiConnectionWidget::modeChanged); +#else + connect(m_ui->modeComboBox, QOverload::of(&KComboBox::currentIndexChanged), this, &WifiConnectionWidget::modeChanged); +#endif +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->band, QOverload::of(&KComboBox::currentIndexChanged), this, &WifiConnectionWidget::bandChanged); +#else + connect(m_ui->band, QOverload::of(&KComboBox::currentIndexChanged), this, &WifiConnectionWidget::bandChanged); +#endif // Connect for setting check watchChangedSetting(); // Connect for validity check connect(m_ui->macAddress, &HwAddrComboBox::hwAddressChanged, this, &WifiConnectionWidget::slotWidgetChanged); connect(m_ui->BSSIDCombo, &BssidComboBox::bssidChanged, this, &WifiConnectionWidget::slotWidgetChanged); KAcceleratorManager::manage(this); if (setting) { loadConfig(setting); } } WifiConnectionWidget::~WifiConnectionWidget() { delete m_ui; } void WifiConnectionWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { NetworkManager::WirelessSetting::Ptr wifiSetting = setting.staticCast(); m_ui->SSIDCombo->init(QString::fromUtf8(wifiSetting->ssid())); if (wifiSetting->mode() != NetworkManager::WirelessSetting::Infrastructure) { m_ui->modeComboBox->setCurrentIndex(wifiSetting->mode()); } modeChanged(wifiSetting->mode()); m_ui->BSSIDCombo->init(NetworkManager::macAddressAsString(wifiSetting->bssid()), QString::fromUtf8(wifiSetting->ssid())); m_ui->band->setCurrentIndex(wifiSetting->band()); if (wifiSetting->band() != NetworkManager::WirelessSetting::Automatic) { m_ui->channel->setCurrentIndex(m_ui->channel->findData(wifiSetting->channel())); } m_ui->macAddress->init(NetworkManager::Device::Wifi, NetworkManager::macAddressAsString(wifiSetting->macAddress())); if (!wifiSetting->clonedMacAddress().isEmpty()) { m_ui->clonedMacAddress->setText(NetworkManager::macAddressAsString(wifiSetting->clonedMacAddress())); } if (wifiSetting->mtu()) { m_ui->mtu->setValue(wifiSetting->mtu()); } if (wifiSetting->hidden()) { m_ui->hiddenNetwork->setChecked(true); } } QVariantMap WifiConnectionWidget::setting() const { NetworkManager::WirelessSetting wifiSetting; wifiSetting.setSsid(m_ui->SSIDCombo->ssid().toUtf8()); wifiSetting.setMode(static_cast(m_ui->modeComboBox->currentIndex())); wifiSetting.setBssid(NetworkManager::macAddressFromString(m_ui->BSSIDCombo->bssid())); if (wifiSetting.mode() != NetworkManager::WirelessSetting::Infrastructure && m_ui->band->currentIndex() != 0) { wifiSetting.setBand((NetworkManager::WirelessSetting::FrequencyBand)m_ui->band->currentIndex()); wifiSetting.setChannel(m_ui->channel->itemData(m_ui->channel->currentIndex()).toUInt()); } wifiSetting.setMacAddress(NetworkManager::macAddressFromString(m_ui->macAddress->hwAddress())); if (!m_ui->clonedMacAddress->text().isEmpty() && m_ui->clonedMacAddress->text() != ":::::") { wifiSetting.setClonedMacAddress(NetworkManager::macAddressFromString(m_ui->clonedMacAddress->text())); } if (m_ui->mtu->value()) { wifiSetting.setMtu(m_ui->mtu->value()); } wifiSetting.setHidden(m_ui->hiddenNetwork->isChecked()); return wifiSetting.toMap(); } void WifiConnectionWidget::generateRandomClonedMac() { QByteArray mac; auto *generator = QRandomGenerator::global(); mac.resize(6); for (int i = 0; i < 6; i++) { const int random = generator->bounded(255); mac[i] = random; } // Disable the multicast bit and enable the locally administered bit. mac[0] = mac[0] & ~0x1; mac[0] = mac[0] | 0x2; m_ui->clonedMacAddress->setText(NetworkManager::macAddressAsString(mac)); } void WifiConnectionWidget::ssidChanged() { m_ui->BSSIDCombo->init(m_ui->BSSIDCombo->bssid(), m_ui->SSIDCombo->ssid()); slotWidgetChanged(); // Emit that SSID has changed so we can pre-configure wireless security Q_EMIT ssidChanged(m_ui->SSIDCombo->ssid()); } void WifiConnectionWidget::modeChanged(int mode) { if (mode == NetworkManager::WirelessSetting::Infrastructure) { m_ui->BSSIDLabel->setVisible(true); m_ui->BSSIDCombo->setVisible(true); m_ui->bandLabel->setVisible(false); m_ui->band->setVisible(false); m_ui->channelLabel->setVisible(false); m_ui->channel->setVisible(false); } else { m_ui->BSSIDLabel->setVisible(false); m_ui->BSSIDCombo->setVisible(false); m_ui->bandLabel->setVisible(true); m_ui->band->setVisible(true); m_ui->channelLabel->setVisible(true); m_ui->channel->setVisible(true); } } void WifiConnectionWidget::bandChanged(int band) { m_ui->channel->clear(); if (band == NetworkManager::WirelessSetting::Automatic) { m_ui->channel->setEnabled(false); } else { fillChannels((NetworkManager::WirelessSetting::FrequencyBand)band); m_ui->channel->setEnabled(true); } } void WifiConnectionWidget::fillChannels(NetworkManager::WirelessSetting::FrequencyBand band) { QList > channels; if (band == NetworkManager::WirelessSetting::A) { channels = NetworkManager::getAFreqs(); } else if (band == NetworkManager::WirelessSetting::Bg) { channels = NetworkManager::getBFreqs(); } else { qCWarning(PLASMA_NM) << Q_FUNC_INFO << "Unhandled band number" << band; return; } QListIterator > i(channels); while (i.hasNext()) { QPair channel = i.next(); m_ui->channel->addItem(i18n("%1 (%2 MHz)", channel.first, channel.second), channel.first); } } bool WifiConnectionWidget::isValid() const { return !m_ui->SSIDCombo->currentText().isEmpty() && m_ui->macAddress->isValid() && m_ui->BSSIDCombo->isValid(); } diff --git a/libs/editor/settings/wifisecurity.cpp b/libs/editor/settings/wifisecurity.cpp index f16588ae..bd40f65f 100644 --- a/libs/editor/settings/wifisecurity.cpp +++ b/libs/editor/settings/wifisecurity.cpp @@ -1,418 +1,434 @@ /* Copyright (c) 2013 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "wifisecurity.h" #include "ui_wifisecurity.h" #include #include #include #include WifiSecurity::WifiSecurity(const NetworkManager::Setting::Ptr &setting, const NetworkManager::Security8021xSetting::Ptr &setting8021x, QWidget *parent, Qt::WindowFlags f) : SettingWidget(setting, parent, f) , m_ui(new Ui::WifiSecurity) { m_wifiSecurity = setting.staticCast(); m_ui->setupUi(this); m_ui->leapPassword->setPasswordOptionsEnabled(true); m_ui->psk->setPasswordOptionsEnabled(true); m_ui->wepKey->setPasswordOptionsEnabled(true); m_8021xWidget = new Security8021x(setting8021x, true, this); // Dynamic WEP m_WPA2Widget = new Security8021x(setting8021x, true, this); // WPA(2) Enterprise m_ui->stackedWidget->insertWidget(3, m_8021xWidget); m_ui->stackedWidget->insertWidget(5, m_WPA2Widget); // WPA3 Personal is available in NM 1.16+ if (!NetworkManager::checkVersion(1, 16, 0)) { m_ui->securityCombo->removeItem(7); } +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->securityCombo, QOverload::of(&KComboBox::currentIndexChanged), this, &WifiSecurity::securityChanged); +#else + connect(m_ui->securityCombo, QOverload::of(&KComboBox::currentIndexChanged), this, &WifiSecurity::securityChanged); +#endif +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->wepIndex, QOverload::of(&KComboBox::currentIndexChanged), this, &WifiSecurity::setWepKey); +#else + connect(m_ui->wepIndex, QOverload::of(&KComboBox::currentIndexChanged), this, &WifiSecurity::setWepKey); +#endif // Connect for setting check watchChangedSetting(); // Connect for validity check connect(m_ui->wepKey, &PasswordField::textChanged, this, &WifiSecurity::slotWidgetChanged); connect(m_ui->wepKey, &PasswordField::passwordOptionChanged, this, &WifiSecurity::slotWidgetChanged); connect(m_ui->leapUsername, &KLineEdit::textChanged, this, &WifiSecurity::slotWidgetChanged); connect(m_ui->leapPassword, &PasswordField::textChanged, this, &WifiSecurity::slotWidgetChanged); connect(m_ui->leapPassword, &PasswordField::passwordOptionChanged, this, &WifiSecurity::slotWidgetChanged); connect(m_ui->psk, &PasswordField::textChanged, this, &WifiSecurity::slotWidgetChanged); connect(m_ui->psk, &PasswordField::passwordOptionChanged, this, &WifiSecurity::slotWidgetChanged); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->wepIndex, QOverload::of(&KComboBox::currentIndexChanged), this, &WifiSecurity::slotWidgetChanged); +#else + connect(m_ui->wepIndex, QOverload::of(&KComboBox::currentIndexChanged), this, &WifiSecurity::slotWidgetChanged); +#endif +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->securityCombo, QOverload::of(&KComboBox::currentIndexChanged), this, &WifiSecurity::slotWidgetChanged); +#else + connect(m_ui->securityCombo, QOverload::of(&KComboBox::currentIndexChanged), this, &WifiSecurity::slotWidgetChanged); +#endif connect(m_8021xWidget, &Security8021x::validChanged, this, &WifiSecurity::slotWidgetChanged); connect(m_WPA2Widget, &Security8021x::validChanged, this, &WifiSecurity::slotWidgetChanged); KAcceleratorManager::manage(this); if (setting && !setting->isNull()) { loadConfig(setting); } } WifiSecurity::~WifiSecurity() { delete m_ui; } bool WifiSecurity::enabled() const { return m_ui->securityCombo->currentIndex() > 0; } bool WifiSecurity::enabled8021x() const { if (m_ui->securityCombo->currentIndex() == 4 || m_ui->securityCombo->currentIndex() == 6) { return true; } return false; } bool WifiSecurity::isValid() const { const int securityIndex = m_ui->securityCombo->currentIndex(); if (securityIndex == WepHex) { // WEP Hex return NetworkManager::wepKeyIsValid(m_ui->wepKey->text(), NetworkManager::WirelessSecuritySetting::Hex) || m_ui->wepKey->passwordOption() == PasswordField::AlwaysAsk; } else if (securityIndex == WepPassphrase) { // WEP Passphrase return NetworkManager::wepKeyIsValid(m_ui->wepKey->text(), NetworkManager::WirelessSecuritySetting::Passphrase) || m_ui->wepKey->passwordOption() == PasswordField::AlwaysAsk;; }else if (securityIndex == Leap) { // LEAP return !m_ui->leapUsername->text().isEmpty() && (!m_ui->leapPassword->text().isEmpty() || m_ui->leapPassword->passwordOption() == PasswordField::AlwaysAsk); } else if (securityIndex == WpaPsk) { // WPA return NetworkManager::wpaPskIsValid(m_ui->psk->text()) || m_ui->psk->passwordOption() == PasswordField::AlwaysAsk; } else if (securityIndex == DynamicWep) { return m_8021xWidget->isValid(); } else if (securityIndex == WpaEap) { return m_WPA2Widget->isValid(); } else if (securityIndex == SAE) { return !m_ui->psk->text().isEmpty() || m_ui->psk->passwordOption() == PasswordField::AlwaysAsk; } return true; } void WifiSecurity::loadConfig(const NetworkManager::Setting::Ptr &setting) { NetworkManager::WirelessSecuritySetting::Ptr wifiSecurity = setting.staticCast(); const NetworkManager::WirelessSecuritySetting::KeyMgmt keyMgmt = wifiSecurity->keyMgmt(); const NetworkManager::WirelessSecuritySetting::AuthAlg authAlg = wifiSecurity->authAlg(); if (keyMgmt == NetworkManager::WirelessSecuritySetting::Unknown) { m_ui->securityCombo->setCurrentIndex(None); // None } else if (keyMgmt == NetworkManager::WirelessSecuritySetting::Wep) { if (wifiSecurity->wepKeyType() == NetworkManager::WirelessSecuritySetting::Hex || wifiSecurity->wepKeyType() == NetworkManager::WirelessSecuritySetting::NotSpecified) { m_ui->securityCombo->setCurrentIndex(WepHex); // WEP Hex } else { m_ui->securityCombo->setCurrentIndex(WepPassphrase); } const int keyIndex = static_cast(wifiSecurity->wepTxKeyindex()); m_ui->wepIndex->setCurrentIndex(keyIndex); if (wifiSecurity->authAlg() == NetworkManager::WirelessSecuritySetting::Open) { m_ui->wepAuth->setCurrentIndex(0); } else { m_ui->wepAuth->setCurrentIndex(1); } if (wifiSecurity->wepKeyFlags().testFlag(NetworkManager::Setting::None)) { m_ui->wepKey->setPasswordOption(PasswordField::StoreForAllUsers); } else if (wifiSecurity->wepKeyFlags().testFlag(NetworkManager::Setting::AgentOwned)) { m_ui->wepKey->setPasswordOption(PasswordField::StoreForUser); } else { m_ui->wepKey->setPasswordOption(PasswordField::AlwaysAsk); } } else if (keyMgmt == NetworkManager::WirelessSecuritySetting::Ieee8021x && authAlg == NetworkManager::WirelessSecuritySetting::Leap) { m_ui->securityCombo->setCurrentIndex(Leap); // LEAP m_ui->leapUsername->setText(wifiSecurity->leapUsername()); m_ui->leapPassword->setText(wifiSecurity->leapPassword()); if (wifiSecurity->leapPasswordFlags().testFlag(NetworkManager::Setting::None)) { m_ui->leapPassword->setPasswordOption(PasswordField::StoreForAllUsers); } else if (wifiSecurity->leapPasswordFlags().testFlag(NetworkManager::Setting::AgentOwned)) { m_ui->leapPassword->setPasswordOption(PasswordField::StoreForUser); } else { m_ui->leapPassword->setPasswordOption(PasswordField::AlwaysAsk); } } else if (keyMgmt == NetworkManager::WirelessSecuritySetting::Ieee8021x) { m_ui->securityCombo->setCurrentIndex(DynamicWep); // Dynamic WEP // done in the widget } else if (keyMgmt == NetworkManager::WirelessSecuritySetting::WpaPsk) { m_ui->securityCombo->setCurrentIndex(WpaPsk); // WPA if (wifiSecurity->pskFlags().testFlag(NetworkManager::Setting::None)) { m_ui->psk->setPasswordOption(PasswordField::StoreForAllUsers); } else if (wifiSecurity->pskFlags().testFlag(NetworkManager::Setting::AgentOwned)) { m_ui->psk->setPasswordOption(PasswordField::StoreForUser); } else { m_ui->psk->setPasswordOption(PasswordField::AlwaysAsk); } } else if (keyMgmt == NetworkManager::WirelessSecuritySetting::WpaEap) { m_ui->securityCombo->setCurrentIndex(WpaEap); // WPA2 Enterprise // done in the widget } else if (keyMgmt == NetworkManager::WirelessSecuritySetting::SAE) { m_ui->securityCombo->setCurrentIndex(SAE); // WPA3 if (wifiSecurity->pskFlags().testFlag(NetworkManager::Setting::None)) { m_ui->psk->setPasswordOption(PasswordField::StoreForAllUsers); } else if (wifiSecurity->pskFlags().testFlag(NetworkManager::Setting::AgentOwned)) { m_ui->psk->setPasswordOption(PasswordField::StoreForUser); } else { m_ui->psk->setPasswordOption(PasswordField::AlwaysAsk); } } if (keyMgmt != NetworkManager::WirelessSecuritySetting::Ieee8021x && keyMgmt != NetworkManager::WirelessSecuritySetting::WpaEap) { loadSecrets(setting); } } void WifiSecurity::loadSecrets(const NetworkManager::Setting::Ptr &setting) { const NetworkManager::WirelessSecuritySetting::KeyMgmt keyMgmt = m_wifiSecurity->keyMgmt(); const NetworkManager::WirelessSecuritySetting::AuthAlg authAlg = m_wifiSecurity->authAlg(); if ((keyMgmt == NetworkManager::WirelessSecuritySetting::Ieee8021x && authAlg != NetworkManager::WirelessSecuritySetting::Leap) || keyMgmt == NetworkManager::WirelessSecuritySetting::WpaEap) { NetworkManager::Security8021xSetting::Ptr security8021xSetting = setting.staticCast(); if (security8021xSetting) { if (keyMgmt == NetworkManager::WirelessSecuritySetting::Ieee8021x) { m_8021xWidget->loadSecrets(security8021xSetting); } else { m_WPA2Widget->loadSecrets(security8021xSetting); } } } else { NetworkManager::WirelessSecuritySetting::Ptr wifiSecurity = setting.staticCast(); if (wifiSecurity) { if (keyMgmt == NetworkManager::WirelessSecuritySetting::Wep) { m_wifiSecurity->secretsFromMap(wifiSecurity->secretsToMap()); const int keyIndex = static_cast(m_wifiSecurity->wepTxKeyindex()); setWepKey(keyIndex); } else if (keyMgmt == NetworkManager::WirelessSecuritySetting::Ieee8021x && authAlg == NetworkManager::WirelessSecuritySetting::Leap) { const QString leapPassword = wifiSecurity->leapPassword(); if (!leapPassword.isEmpty()) { m_ui->leapPassword->setText(leapPassword); } } else if (keyMgmt == NetworkManager::WirelessSecuritySetting::WpaPsk || keyMgmt == NetworkManager::WirelessSecuritySetting::SAE) { const QString psk = wifiSecurity->psk(); if (!psk.isEmpty()) { m_ui->psk->setText(psk); } } } } } QVariantMap WifiSecurity::setting() const { NetworkManager::WirelessSecuritySetting wifiSecurity; const int securityIndex = m_ui->securityCombo->currentIndex(); if (securityIndex == None) { wifiSecurity.setKeyMgmt(NetworkManager::WirelessSecuritySetting::Unknown); } else if (securityIndex == WepHex || securityIndex == WepPassphrase) { // WEP wifiSecurity.setKeyMgmt(NetworkManager::WirelessSecuritySetting::Wep); if (securityIndex == WepHex) { wifiSecurity.setWepKeyType(NetworkManager::WirelessSecuritySetting::Hex); } else { wifiSecurity.setWepKeyType(NetworkManager::WirelessSecuritySetting::Passphrase); } const int keyIndex = m_ui->wepIndex->currentIndex(); const QString wepKey = m_ui->wepKey->text(); wifiSecurity.setWepTxKeyindex(keyIndex); if (keyIndex == 0) { wifiSecurity.setWepKey0(wepKey); } else if (keyIndex == 1) { wifiSecurity.setWepKey1(wepKey); } else if (keyIndex == 2) { wifiSecurity.setWepKey2(wepKey); } else if (keyIndex == 3) { wifiSecurity.setWepKey3(wepKey); } if (m_ui->wepKey->passwordOption() == PasswordField::StoreForAllUsers) { wifiSecurity.setWepKeyFlags(NetworkManager::Setting::None); } else if (m_ui->wepKey->passwordOption() == PasswordField::StoreForUser) { wifiSecurity.setWepKeyFlags(NetworkManager::Setting::AgentOwned); } else { wifiSecurity.setWepKeyFlags(NetworkManager::Setting::NotSaved); } if (m_ui->wepAuth->currentIndex() == 0) { wifiSecurity.setAuthAlg(NetworkManager::WirelessSecuritySetting::Open); } else { wifiSecurity.setAuthAlg(NetworkManager::WirelessSecuritySetting::Shared); } } else if (securityIndex == Leap) { // LEAP wifiSecurity.setKeyMgmt(NetworkManager::WirelessSecuritySetting::Ieee8021x); wifiSecurity.setAuthAlg(NetworkManager::WirelessSecuritySetting::Leap); wifiSecurity.setLeapUsername(m_ui->leapUsername->text()); wifiSecurity.setLeapPassword(m_ui->leapPassword->text()); if (m_ui->leapPassword->passwordOption() == PasswordField::StoreForAllUsers) { wifiSecurity.setLeapPasswordFlags(NetworkManager::Setting::None); } else if (m_ui->leapPassword->passwordOption() == PasswordField::StoreForUser) { wifiSecurity.setLeapPasswordFlags(NetworkManager::Setting::AgentOwned); } else { wifiSecurity.setLeapPasswordFlags(NetworkManager::Setting::NotSaved); } } else if (securityIndex == DynamicWep) { // Dynamic WEP wifiSecurity.setKeyMgmt(NetworkManager::WirelessSecuritySetting::Ieee8021x); } else if (securityIndex == WpaPsk) { // WPA wifiSecurity.setKeyMgmt(NetworkManager::WirelessSecuritySetting::WpaPsk); wifiSecurity.setPsk(m_ui->psk->text()); if (m_ui->psk->passwordOption() == PasswordField::StoreForAllUsers) { wifiSecurity.setPskFlags(NetworkManager::Setting::None); } else if (m_ui->psk->passwordOption() == PasswordField::StoreForUser) { wifiSecurity.setPskFlags(NetworkManager::Setting::AgentOwned); } else { wifiSecurity.setPskFlags(NetworkManager::Setting::NotSaved); } } else if (securityIndex == WpaEap) { // WPA2 Enterprise wifiSecurity.setKeyMgmt(NetworkManager::WirelessSecuritySetting::WpaEap); } else if (securityIndex == SAE) { // WPA3 Personal wifiSecurity.setKeyMgmt(NetworkManager::WirelessSecuritySetting::SAE); wifiSecurity.setPsk(m_ui->psk->text()); if (m_ui->psk->passwordOption() == PasswordField::StoreForAllUsers) { wifiSecurity.setPskFlags(NetworkManager::Setting::None); } else if (m_ui->psk->passwordOption() == PasswordField::StoreForUser) { wifiSecurity.setPskFlags(NetworkManager::Setting::AgentOwned); } else { wifiSecurity.setPskFlags(NetworkManager::Setting::NotSaved); } } return wifiSecurity.toMap(); } QVariantMap WifiSecurity::setting8021x() const { if (m_ui->securityCombo->currentIndex() == DynamicWep) { // Dynamic WEP return m_8021xWidget->setting(); } else if (m_ui->securityCombo->currentIndex() == WpaEap) { // WPA2 Enterprise return m_WPA2Widget->setting(); } return QVariantMap(); } void WifiSecurity::onSsidChanged(const QString &ssid) { for (const NetworkManager::Device::Ptr &device : NetworkManager::networkInterfaces()) { if (device->type() == NetworkManager::Device::Wifi) { NetworkManager::WirelessDevice::Ptr wifiDevice = device.staticCast(); if (wifiDevice) { for (const NetworkManager::WirelessNetwork::Ptr wifiNetwork : wifiDevice->networks()) { if (wifiNetwork && wifiNetwork->ssid() == ssid) { NetworkManager::AccessPoint::Ptr ap = wifiNetwork->referenceAccessPoint(); NetworkManager::WirelessSecurityType securityType = NetworkManager::findBestWirelessSecurity(wifiDevice->wirelessCapabilities(), true, (wifiDevice->mode() == NetworkManager::WirelessDevice::Adhoc), ap->capabilities(), ap->wpaFlags(), ap->rsnFlags()); switch (securityType) { case NetworkManager::WirelessSecurityType::StaticWep: m_ui->securityCombo->setCurrentIndex(WepHex); break; case NetworkManager::WirelessSecurityType::DynamicWep: m_ui->securityCombo->setCurrentIndex(DynamicWep); break; case NetworkManager::WirelessSecurityType::Leap: m_ui->securityCombo->setCurrentIndex(Leap); break; case NetworkManager::WirelessSecurityType::WpaPsk: m_ui->securityCombo->setCurrentIndex(WpaPsk); break; case NetworkManager::WirelessSecurityType::Wpa2Psk: m_ui->securityCombo->setCurrentIndex(WpaPsk); break; case NetworkManager::WirelessSecurityType::WpaEap: m_ui->securityCombo->setCurrentIndex(WpaEap); break; case NetworkManager::WirelessSecurityType::Wpa2Eap: m_ui->securityCombo->setCurrentIndex(WpaEap); break; case NetworkManager::WirelessSecurityType::SAE: m_ui->securityCombo->setCurrentIndex(SAE); break; default: m_ui->securityCombo->setCurrentIndex(None); } return; } } } } } // Reset to none security if we don't find any AP or Wifi device m_ui->securityCombo->setCurrentIndex(None); } void WifiSecurity::setWepKey(int keyIndex) { if (keyIndex == 0) { m_ui->wepKey->setText(m_wifiSecurity->wepKey0()); } else if (keyIndex == 1) { m_ui->wepKey->setText(m_wifiSecurity->wepKey1()); } else if (keyIndex == 2) { m_ui->wepKey->setText(m_wifiSecurity->wepKey2()); } else if (keyIndex == 3) { m_ui->wepKey->setText(m_wifiSecurity->wepKey3()); } } void WifiSecurity::securityChanged(int index) { if (index == None) { m_ui->stackedWidget->setCurrentIndex(0); } else if (index == WepHex || index == WepPassphrase) { m_ui->stackedWidget->setCurrentIndex(1); } else if (index == Leap) { m_ui->stackedWidget->setCurrentIndex(2); } else if (index == DynamicWep) { m_ui->stackedWidget->setCurrentIndex(3); } else if (index == WpaPsk || index == SAE) { m_ui->stackedWidget->setCurrentIndex(4); } else if (index == WpaEap) { m_ui->stackedWidget->setCurrentIndex(5); } KAcceleratorManager::manage(m_ui->stackedWidget->currentWidget()); } diff --git a/libs/editor/settings/wiredconnectionwidget.cpp b/libs/editor/settings/wiredconnectionwidget.cpp index b9851942..6694f2a3 100644 --- a/libs/editor/settings/wiredconnectionwidget.cpp +++ b/libs/editor/settings/wiredconnectionwidget.cpp @@ -1,181 +1,185 @@ /* Copyright 2013 Jan Grulich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "wiredconnectionwidget.h" #include "ui_wiredconnectionwidget.h" #include "uiutils.h" #include #include #include WiredConnectionWidget::WiredConnectionWidget(const NetworkManager::Setting::Ptr &setting, QWidget* parent, Qt::WindowFlags f): SettingWidget(setting, parent, f), m_widget(new Ui::WiredConnectionWidget) { m_widget->setupUi(this); connect(m_widget->btnRandomMacAddr, &QPushButton::clicked, this, &WiredConnectionWidget::generateRandomClonedMac); // Connect for setting check watchChangedSetting(); // Connect for validity check connect(m_widget->clonedMacAddress, &KLineEdit::textChanged, this, &WiredConnectionWidget::slotWidgetChanged); connect(m_widget->macAddress, &HwAddrComboBox::hwAddressChanged, this, &WiredConnectionWidget::slotWidgetChanged); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_widget->linkNegotiation, QOverload::of(&QComboBox::currentIndexChanged), this, [this] (int index) { +#else + connect(m_widget->linkNegotiation, QOverload::of(&QComboBox::currentIndexChanged), this, [this] (int index) { +#endif m_widget->duplex->setEnabled(index == LinkNegotiation::Manual); m_widget->speed->setEnabled(index == LinkNegotiation::Manual); }); KAcceleratorManager::manage(this); if (setting) { loadConfig(setting); } } WiredConnectionWidget::~WiredConnectionWidget() { delete m_widget; } void WiredConnectionWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { NetworkManager::WiredSetting::Ptr wiredSetting = setting.staticCast(); m_widget->macAddress->init(NetworkManager::Device::Ethernet, NetworkManager::macAddressAsString(wiredSetting->macAddress())); if (!wiredSetting->clonedMacAddress().isEmpty()) { m_widget->clonedMacAddress->setText(NetworkManager::macAddressAsString(wiredSetting->clonedMacAddress())); } if (wiredSetting->mtu()) { m_widget->mtu->setValue(wiredSetting->mtu()); } if (wiredSetting->autoNegotiate()) { m_widget->linkNegotiation->setCurrentIndex(LinkNegotiation::Automatic); } else if (wiredSetting->speed() && wiredSetting->duplexType() != NetworkManager::WiredSetting::UnknownDuplexType) { m_widget->linkNegotiation->setCurrentIndex(LinkNegotiation::Manual); } if (wiredSetting->speed()) { switch(wiredSetting->speed()) { case 10: m_widget->speed->setCurrentIndex(0); break; case 100: m_widget->speed->setCurrentIndex(1); break; case 1000: m_widget->speed->setCurrentIndex(2); break; case 10000: m_widget->speed->setCurrentIndex(3); break; } } if (wiredSetting->duplexType() != NetworkManager::WiredSetting::Half) { m_widget->duplex->setCurrentIndex(Duplex::Full); } else { m_widget->duplex->setCurrentIndex(Duplex::Half); } } QVariantMap WiredConnectionWidget::setting() const { NetworkManager::WiredSetting wiredSetting; wiredSetting.setMacAddress(NetworkManager::macAddressFromString(m_widget->macAddress->hwAddress())); if (!m_widget->clonedMacAddress->text().isEmpty() && m_widget->clonedMacAddress->text() != ":::::") { wiredSetting.setClonedMacAddress(NetworkManager::macAddressFromString(m_widget->clonedMacAddress->text())); } if (m_widget->mtu->value()) { wiredSetting.setMtu(m_widget->mtu->value()); } if (m_widget->linkNegotiation->currentIndex() == LinkNegotiation::Automatic || m_widget->linkNegotiation->currentIndex() == LinkNegotiation::Ignore) { wiredSetting.setDuplexType(NetworkManager::WiredSetting::UnknownDuplexType); wiredSetting.setSpeed(0); } else { switch (m_widget->speed->currentIndex()) { case 0: wiredSetting.setSpeed(10); break; case 1: wiredSetting.setSpeed(100); break; case 2: wiredSetting.setSpeed(1000); break; case 3: wiredSetting.setSpeed(10000); break; } if (m_widget->duplex->currentIndex() == Duplex::Full) { wiredSetting.setDuplexType(NetworkManager::WiredSetting::Full); } else { wiredSetting.setDuplexType(NetworkManager::WiredSetting::Half); } } wiredSetting.setAutoNegotiate(m_widget->linkNegotiation->currentIndex() == LinkNegotiation::Automatic); return wiredSetting.toMap(); } void WiredConnectionWidget::generateRandomClonedMac() { auto *generator = QRandomGenerator::global(); QByteArray mac; mac.resize(6); for (int i = 0; i < 6; i++) { const int random = generator->bounded(255); mac[i] = random; } // Disable the multicast bit and enable the locally administered bit. mac[0] = mac[0] & ~0x1; mac[0] = mac[0] | 0x2; m_widget->clonedMacAddress->setText(NetworkManager::macAddressAsString(mac)); } bool WiredConnectionWidget::isValid() const { if (!m_widget->macAddress->isValid()) { return false; } if (m_widget->clonedMacAddress->text() != ":::::") { if (!NetworkManager::macAddressIsValid(m_widget->clonedMacAddress->text())) { return false; } } return true; } diff --git a/libs/editor/widgets/passwordfield.cpp b/libs/editor/widgets/passwordfield.cpp index 377fdeeb..0eb13dcb 100644 --- a/libs/editor/widgets/passwordfield.cpp +++ b/libs/editor/widgets/passwordfield.cpp @@ -1,181 +1,185 @@ /* Copyright 2015 Jan Grulich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "passwordfield.h" #include #include #include #include #include PasswordField::PasswordField(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f) , m_currentPasswordOption(StoreForUser) { m_layout = new QVBoxLayout(this); // The widget will be already in layout, thus reset content margins // to align it with the rest of widgets m_layout->setContentsMargins(0, 0, 0, 0); m_passwordField = new QLineEdit(this); connect(m_passwordField, &QLineEdit::textChanged, this, &PasswordField::textChanged); if (KAuthorized::authorize(QStringLiteral("lineedit_reveal_password"))) { m_toggleEchoModeAction = m_passwordField->addAction(QIcon::fromTheme(QStringLiteral("visibility")), QLineEdit::TrailingPosition); m_toggleEchoModeAction->setVisible(false); m_toggleEchoModeAction->setToolTip(i18n("Change the visibility of the password")); connect(m_passwordField, &QLineEdit::textChanged, this, &PasswordField::showToggleEchoModeAction); connect(m_toggleEchoModeAction, &QAction::triggered, this, &PasswordField::toggleEchoMode); } m_layout->addWidget(m_passwordField); m_passwordOptionsMenu = new QComboBox(this); m_passwordOptionsMenu->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); m_passwordOptionsMenu->addItem(QIcon::fromTheme(QStringLiteral("document-save")), i18n("Store password for this user only (encrypted)"), StoreForUser); m_passwordOptionsMenu->addItem(QIcon::fromTheme(QStringLiteral("document-save-all")), i18n("Store password for all users (not encrypted)"), StoreForAllUsers); m_passwordOptionsMenu->addItem(QIcon::fromTheme(QStringLiteral("dialog-messages")), i18n("Ask for this password every time"), AlwaysAsk); // Do not add by default // m_passwordOptionsMenu->addItem(QIcon::fromTheme(QStringLiteral("document-close")), i18n("This password is not required"), NotRequired); if (KWallet::Wallet::isEnabled()) { m_passwordOptionsMenu->setCurrentIndex(0); } else { m_passwordOptionsMenu->setCurrentIndex(1); m_currentPasswordOption = StoreForAllUsers; } +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_passwordOptionsMenu, QOverload::of(&QComboBox::currentIndexChanged), this, &PasswordField::changePasswordOption); +#else + connect(m_passwordOptionsMenu, QOverload::of(&QComboBox::currentIndexChanged), this, &PasswordField::changePasswordOption); +#endif // Disable by default m_passwordOptionsMenu->setVisible(false); // m_layout->addWidget(m_passwordOptionsMenu); setLayout(m_layout); } void PasswordField::setMaxLength(int maxLength) { m_passwordField->setMaxLength(maxLength); } void PasswordField::setPasswordModeEnabled(bool enable) { m_passwordField->setEchoMode(enable ? QLineEdit::Password : QLineEdit::Normal); } void PasswordField::setPasswordOptionsEnabled(bool enable) { if (enable) { m_layout->addWidget(m_passwordOptionsMenu); m_passwordOptionsMenu->setVisible(true); } else { m_layout->removeWidget(m_passwordOptionsMenu); m_passwordOptionsMenu->setVisible(false); } } void PasswordField::setPasswordNotSavedEnabled(bool enable) { if (enable) { const int index = m_passwordOptionsMenu->findData(AlwaysAsk); if (index == -1) { m_passwordOptionsMenu->addItem(QIcon::fromTheme(QStringLiteral("dialog-messages")), i18n("Ask for this password every time"), AlwaysAsk); } } else { const int index = m_passwordOptionsMenu->findData(AlwaysAsk); if (index != -1) { m_passwordOptionsMenu->removeItem(index); } } } void PasswordField::setPasswordNotRequiredEnabled(bool enable) { if (enable) { const int index = m_passwordOptionsMenu->findData(NotRequired); if (index == -1) { m_passwordOptionsMenu->addItem(QIcon::fromTheme(QStringLiteral("document-close")), i18n("This password is not required"), NotRequired); } } else { const int index = m_passwordOptionsMenu->findData(NotRequired); if (index != -1) { m_passwordOptionsMenu->removeItem(index); } } } void PasswordField::setText(const QString &text) { m_passwordField->setText(text); } QString PasswordField::text() const { return m_passwordField->text(); } PasswordField::PasswordOption PasswordField::passwordOption() const { return m_currentPasswordOption; } void PasswordField::setPasswordOption(PasswordField::PasswordOption option) { const int index = m_passwordOptionsMenu->findData(option); if (index != -1) { m_passwordOptionsMenu->setCurrentIndex(index); } } void PasswordField::showToggleEchoModeAction(const QString &text) { m_toggleEchoModeAction->setVisible(!text.isEmpty()); } void PasswordField::toggleEchoMode() { if (m_passwordField->echoMode() == QLineEdit::Password) { m_passwordField->setEchoMode(QLineEdit::Normal); m_toggleEchoModeAction->setIcon(QIcon::fromTheme(QStringLiteral("hint"))); } else if (m_passwordField->echoMode() == QLineEdit::Normal) { m_passwordField->setEchoMode(QLineEdit::Password); m_toggleEchoModeAction->setIcon(QIcon::fromTheme(QStringLiteral("visibility"))); } } void PasswordField::changePasswordOption(int index) { Q_UNUSED(index); m_currentPasswordOption = (PasswordOption)m_passwordOptionsMenu->currentData().toUInt(); if (m_currentPasswordOption == PasswordField::NotRequired || m_currentPasswordOption == PasswordField::AlwaysAsk) { m_passwordField->clear(); m_passwordField->setDisabled(true); } else { m_passwordField->setEnabled(true); } Q_EMIT passwordOptionChanged(m_currentPasswordOption); } diff --git a/libs/editor/widgets/settingwidget.cpp b/libs/editor/widgets/settingwidget.cpp index 8391a881..c9cd446e 100644 --- a/libs/editor/widgets/settingwidget.cpp +++ b/libs/editor/widgets/settingwidget.cpp @@ -1,149 +1,153 @@ /* Copyright 2013 Jan Grulich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "settingwidget.h" #include "bssidcombobox.h" #include "hwaddrcombobox.h" #include "ssidcombobox.h" #include "passwordfield.h" #include #include #include #include #include #include #include #include SettingWidget::SettingWidget(const NetworkManager::Setting::Ptr &setting, QWidget* parent, Qt::WindowFlags f): QWidget(parent, f), m_type(setting->name()) { } SettingWidget::~SettingWidget() { } void SettingWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { Q_UNUSED(setting); } void SettingWidget::loadSecrets(const NetworkManager::Setting::Ptr &setting) { Q_UNUSED(setting); } void SettingWidget::watchChangedSetting() { // Attempt to connect to all widgets representing various configurations // to notify about setting change /************ Qt Widgets ************/ // Connect all QLineEdit widgets QList lineEdits = findChildren(); for (QLineEdit *lineedit : lineEdits) { connect(lineedit, &QLineEdit::textChanged, this, &SettingWidget::settingChanged); } // Connect all QComboBox widgets QList comboboxes = findChildren(); for (QComboBox *combobox : comboboxes) { +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(combobox, QOverload::of(&QComboBox::currentIndexChanged), this, &SettingWidget::settingChanged); +#else + connect(combobox, QOverload::of(&QComboBox::currentIndexChanged), this, &SettingWidget::settingChanged); +#endif connect(combobox, &QComboBox::currentTextChanged, this, &SettingWidget::settingChanged); } // Connect all QCheckBox widgets QList checkboxes = findChildren(); for (QCheckBox *checkbox : checkboxes) { connect(checkbox, &QCheckBox::stateChanged, this, &SettingWidget::settingChanged); } // Connect all QPushButton widgets QList pushbuttons = findChildren(); for (QPushButton *pushbutton : pushbuttons) { connect(pushbutton, &QPushButton::clicked, this, &SettingWidget::settingChanged); } // Connect all QSpinBox widgets QList spinboxes = findChildren(); for (QSpinBox *spinbox : spinboxes) { connect(spinbox, QOverload::of(&QSpinBox::valueChanged), this, &SettingWidget::settingChanged); } // Connect all KUrlRequester widgets QList urlrequesters = findChildren(); for (KUrlRequester *urlrequester : urlrequesters) { connect(urlrequester, &KUrlRequester::textChanged, this, &SettingWidget::settingChanged); connect(urlrequester, &KUrlRequester::urlSelected, this, &SettingWidget::settingChanged); } // Connect all QTableView widgets QList tableviews = findChildren(); for(QTableView *tableview : tableviews) { connect(tableview, &QTableView::clicked, this, &SettingWidget::settingChanged); } // Connect all QGroupBox widgets QList groupBoxes = findChildren(); for (QGroupBox *box : groupBoxes) { connect(box, &QGroupBox::toggled, this, &SettingWidget::settingChanged); } /********** OUR CUSTOM WIDGETS **********/ // Connect all PasswordField widgets QList passwordfields = findChildren(); for (PasswordField *passwordfield : passwordfields) { connect(passwordfield, &PasswordField::textChanged, this, &SettingWidget::settingChanged); connect(passwordfield, &PasswordField::passwordOptionChanged, this, &SettingWidget::settingChanged); } // Connect all HwAddrComboBox widgets QList hwAddrcomboboxes = findChildren(); for (HwAddrComboBox *combobox : hwAddrcomboboxes) { connect(combobox, &HwAddrComboBox::hwAddressChanged, this, &SettingWidget::settingChanged); } // Connect all SssidComboBox widgets QList ssidcomboboxes = findChildren(); for (SsidComboBox *combobox : ssidcomboboxes) { connect(combobox, &SsidComboBox::ssidChanged, this, &SettingWidget::settingChanged); } // Connect all BssidComboBox widgets QList bssidcomboboxes = findChildren(); for (BssidComboBox *combobox : bssidcomboboxes) { connect(combobox, &BssidComboBox::bssidChanged, this, &SettingWidget::settingChanged); } } QString SettingWidget::type() const { return m_type; } void SettingWidget::slotWidgetChanged() { Q_EMIT validChanged(isValid()); } diff --git a/vpn/openconnect/openconnectauth.cpp b/vpn/openconnect/openconnectauth.cpp index 8f72f76a..3c897867 100644 --- a/vpn/openconnect/openconnectauth.cpp +++ b/vpn/openconnect/openconnectauth.cpp @@ -1,785 +1,797 @@ /* Copyright 2011 Ilia Kats Copyright 2013 Lukáš Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "openconnectauth.h" #include "openconnectauthworkerthread.h" #include "ui_openconnectauth.h" #include "debug.h" #include "passwordfield.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "nm-openconnect-service.h" #include extern "C" { #include #include #include } #if !OPENCONNECT_CHECK_VER(2,1) #define __openconnect_set_token_mode(...) -EOPNOTSUPP #elif !OPENCONNECT_CHECK_VER(2,2) #define __openconnect_set_token_mode(vpninfo, mode, secret) openconnect_set_stoken_mode(vpninfo, 1, secret) #else #define __openconnect_set_token_mode openconnect_set_token_mode #endif #if OPENCONNECT_CHECK_VER(3,4) static int updateToken(void*, const char*); #endif // name/address: IP/domain name of the host (OpenConnect accepts both, so no difference here) // group: user group on the server typedef struct { QString name; QString group; QString address; } VPNHost; typedef struct { oc_token_mode_t tokenMode; QByteArray tokenSecret; } Token; class OpenconnectAuthWidgetPrivate { public: Ui_OpenconnectAuth ui; NetworkManager::VpnSetting::Ptr setting; struct openconnect_info *vpninfo; NMStringMap secrets; NMStringMap tmpSecrets; QMutex mutex; QWaitCondition workerWaiting; OpenconnectAuthWorkerThread *worker; QList hosts; bool userQuit; bool formGroupChanged; int cancelPipes[2]; QList > serverLog; int passwordFormIndex; QByteArray tokenMode; Token token; enum LogLevels {Error = 0, Info, Debug, Trace}; }; OpenconnectAuthWidget::OpenconnectAuthWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget * parent) : SettingWidget(setting, parent) , d_ptr(new OpenconnectAuthWidgetPrivate) { Q_D(OpenconnectAuthWidget); d->setting = setting; d->ui.setupUi(this); d->userQuit = false; d->formGroupChanged = false; if (pipe2(d->cancelPipes, O_NONBLOCK|O_CLOEXEC)) { // Should never happen. Just don't do real cancellation if it does d->cancelPipes[0] = -1; d->cancelPipes[1] = -1; } +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(d->ui.cmbLogLevel, QOverload::of(&QComboBox::currentIndexChanged), this, &OpenconnectAuthWidget::logLevelChanged); +#else + connect(d->ui.cmbLogLevel, QOverload::of(&QComboBox::currentIndexChanged), this, &OpenconnectAuthWidget::logLevelChanged); +#endif connect(d->ui.viewServerLog, &QCheckBox::toggled, this, &OpenconnectAuthWidget::viewServerLogToggled); connect(d->ui.btnConnect, &QPushButton::clicked, this, &OpenconnectAuthWidget::connectHost); d->ui.cmbLogLevel->setCurrentIndex(OpenconnectAuthWidgetPrivate::Debug); d->ui.btnConnect->setIcon(QIcon::fromTheme("network-connect")); d->ui.viewServerLog->setChecked(false); d->worker = new OpenconnectAuthWorkerThread(&d->mutex, &d->workerWaiting, &d->userQuit, &d->formGroupChanged, d->cancelPipes[0]); // gets the pointer to struct openconnect_info (defined in openconnect.h), which contains data that OpenConnect needs, // and which needs to be populated with settings we get from NM, like host, certificate or private key d->vpninfo = d->worker->getOpenconnectInfo(); connect(d->worker, QOverload::of(&OpenconnectAuthWorkerThread::validatePeerCert), this, &OpenconnectAuthWidget::validatePeerCert); connect(d->worker, &OpenconnectAuthWorkerThread::processAuthForm, this, &OpenconnectAuthWidget::processAuthForm); connect(d->worker, &OpenconnectAuthWorkerThread::updateLog, this, &OpenconnectAuthWidget::updateLog); connect(d->worker, QOverload::of(&OpenconnectAuthWorkerThread::writeNewConfig), this, &OpenconnectAuthWidget::writeNewConfig); connect(d->worker, &OpenconnectAuthWorkerThread::cookieObtained, this, &OpenconnectAuthWidget::workerFinished); connect(d->worker, &OpenconnectAuthWorkerThread::initTokens, this, &OpenconnectAuthWidget::initTokens); readConfig(); readSecrets(); #if OPENCONNECT_CHECK_VER(3,4) openconnect_set_token_callbacks(d->vpninfo, &d->secrets, NULL, &updateToken); #endif // This might be set by readSecrets() so don't connect it until now +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(d->ui.cmbHosts, QOverload::of(&QComboBox::currentIndexChanged), this, &OpenconnectAuthWidget::connectHost); +#else + connect(d->ui.cmbHosts, QOverload::of(&QComboBox::currentIndexChanged), this, &OpenconnectAuthWidget::connectHost); +#endif KAcceleratorManager::manage(this); } OpenconnectAuthWidget::~OpenconnectAuthWidget() { Q_D(OpenconnectAuthWidget); d->userQuit = true; if (write(d->cancelPipes[1], "x", 1)) { // not a lot we can do } d->workerWaiting.wakeAll(); d->worker->wait(); ::close(d->cancelPipes[0]); ::close(d->cancelPipes[1]); deleteAllFromLayout(d->ui.loginBoxLayout); delete d->worker; delete d; } void OpenconnectAuthWidget::readConfig() { Q_D(OpenconnectAuthWidget); const NMStringMap dataMap = d->setting->data(); if (!dataMap[NM_OPENCONNECT_KEY_GATEWAY].isEmpty()) { const QString gw = dataMap[NM_OPENCONNECT_KEY_GATEWAY]; VPNHost host; const int index = gw.indexOf(QLatin1Char('/')); if (index > -1) { host.name = host.address = gw.left(index); host.group = gw.right(gw.length() - index - 1); } else { host.name = host.address = gw; } d->hosts.append(host); } if (!dataMap[NM_OPENCONNECT_KEY_CACERT].isEmpty()) { const QByteArray crt = QFile::encodeName(dataMap[NM_OPENCONNECT_KEY_CACERT]); openconnect_set_cafile(d->vpninfo, OC3DUP(crt.data())); } if (dataMap[NM_OPENCONNECT_KEY_CSD_ENABLE] == "yes") { char *wrapper; wrapper = nullptr; if (!dataMap[NM_OPENCONNECT_KEY_CSD_WRAPPER].isEmpty()) { const QByteArray wrapperScript = QFile::encodeName(dataMap[NM_OPENCONNECT_KEY_CSD_WRAPPER]); wrapper = strdup(wrapperScript.data()); } openconnect_setup_csd(d->vpninfo, getuid(), 1, wrapper); } if (!dataMap[NM_OPENCONNECT_KEY_PROXY].isEmpty()) { const QByteArray proxy = QFile::encodeName(dataMap[NM_OPENCONNECT_KEY_PROXY]); openconnect_set_http_proxy(d->vpninfo, OC3DUP(proxy.data())); } if (!dataMap[NM_OPENCONNECT_KEY_USERCERT].isEmpty()) { const QByteArray crt = QFile::encodeName(dataMap[NM_OPENCONNECT_KEY_USERCERT]); const QByteArray key = QFile::encodeName(dataMap[NM_OPENCONNECT_KEY_PRIVKEY]); openconnect_set_client_cert (d->vpninfo, OC3DUP(crt.data()), OC3DUP(key.data())); if (!crt.isEmpty() && dataMap[NM_OPENCONNECT_KEY_PEM_PASSPHRASE_FSID] == "yes") { openconnect_passphrase_from_fsid(d->vpninfo); } } if (!dataMap[NM_OPENCONNECT_KEY_PROTOCOL].isEmpty()) { const QString protocol = dataMap[NM_OPENCONNECT_KEY_PROTOCOL]; openconnect_set_protocol(d->vpninfo, OC3DUP(protocol == "juniper" ? "nc" : protocol.toUtf8().data())); } d->tokenMode = dataMap[NM_OPENCONNECT_KEY_TOKEN_MODE].toUtf8(); } void OpenconnectAuthWidget::readSecrets() { Q_D(OpenconnectAuthWidget); d->secrets = d->setting->secrets(); if (!d->secrets["xmlconfig"].isEmpty()) { const QByteArray config = QByteArray::fromBase64(d->secrets["xmlconfig"].toLatin1()); QCryptographicHash hash(QCryptographicHash::Sha1); hash.addData(config.data(), config.size()); const char *sha1_text = hash.result().toHex(); openconnect_set_xmlsha1 (d->vpninfo, (char *)sha1_text, strlen(sha1_text)+1); QDomDocument xmlconfig; xmlconfig.setContent(config); const QDomNode anyConnectProfile = xmlconfig.elementsByTagName(QLatin1String("AnyConnectProfile")).at(0); bool matchedGw = false; const QDomNode serverList = anyConnectProfile.firstChildElement(QLatin1String("ServerList")); for (QDomElement entry = serverList.firstChildElement(QLatin1String("HostEntry")); !entry.isNull(); entry = entry.nextSiblingElement(QLatin1String("HostEntry"))) { VPNHost host; host.name = entry.firstChildElement(QLatin1String("HostName")).text(); host.group = entry.firstChildElement(QLatin1String("UserGroup")).text(); host.address = entry.firstChildElement(QLatin1String("HostAddress")).text(); // We added the originally configured host in readConfig(). But if // it matches one of the ones in the XML config (as presumably it // should), remove the original and use the one with the pretty name. if (!matchedGw && host.address == d->hosts.at(0).address) { d->hosts.removeFirst(); matchedGw = true; } d->hosts.append(host); } } for (int i = 0; i < d->hosts.size(); i++) { d->ui.cmbHosts->addItem(d->hosts.at(i).name, i); if (d->secrets["lasthost"] == d->hosts.at(i).name || d->secrets["lasthost"] == d->hosts.at(i).address) { d->ui.cmbHosts->setCurrentIndex(i); } } if (d->secrets["autoconnect"] == "yes") { d->ui.chkAutoconnect->setChecked(true); QTimer::singleShot(0, this, &OpenconnectAuthWidget::connectHost); } if (d->secrets["save_passwords"] == "yes") { d->ui.chkStorePasswords->setChecked(true); } d->token.tokenMode = OC_TOKEN_MODE_NONE; d->token.tokenSecret = nullptr; if (!d->tokenMode.isEmpty()) { int ret = 0; QByteArray tokenSecret = d->secrets[NM_OPENCONNECT_KEY_TOKEN_SECRET].toUtf8(); if (d->tokenMode == QStringLiteral("manual") && !tokenSecret.isEmpty()) { ret = __openconnect_set_token_mode(d->vpninfo, OC_TOKEN_MODE_STOKEN, tokenSecret); } else if (d->tokenMode ==QStringLiteral("stokenrc")) { ret = __openconnect_set_token_mode(d->vpninfo, OC_TOKEN_MODE_STOKEN, NULL); } else if (d->tokenMode == QStringLiteral("totp") && !tokenSecret.isEmpty()) { ret = __openconnect_set_token_mode(d->vpninfo, OC_TOKEN_MODE_TOTP, tokenSecret); } #if OPENCONNECT_CHECK_VER(3,4) else if (d->tokenMode == QStringLiteral("hotp") && !tokenSecret.isEmpty()) { ret = __openconnect_set_token_mode(d->vpninfo, OC_TOKEN_MODE_HOTP, tokenSecret); } #endif #if OPENCONNECT_CHECK_VER(5,0) else if (d->tokenMode == "yubioath") { /* This needs to be done from a thread because it can call back to ask for the PIN */ d->token.tokenMode = OC_TOKEN_MODE_YUBIOATH; if (!tokenSecret.isEmpty()) { d->token.tokenSecret = tokenSecret; } } #endif if (ret) { addFormInfo(QLatin1String("dialog-error"), i18n("Failed to initialize software token: %1", ret)); } } } void OpenconnectAuthWidget::acceptDialog() { // Find top-level widget as this should be the QDialog itself QWidget *widget = parentWidget(); while (widget->parentWidget() != nullptr) { widget = widget->parentWidget(); } QDialog *dialog = qobject_cast(widget); if (dialog) { dialog->accept(); } } // This starts the worker thread, which connects to the selected AnyConnect host // and retrieves the login form void OpenconnectAuthWidget::connectHost() { Q_D(OpenconnectAuthWidget); d->userQuit = true; if (write(d->cancelPipes[1], "x", 1)) { // not a lot we can do } d->workerWaiting.wakeAll(); d->worker->wait(); d->userQuit = false; /* Suck out the cancel byte(s) */ char buf; while (read(d->cancelPipes[0], &buf, 1) == 1) { ; } deleteAllFromLayout(d->ui.loginBoxLayout); int i = d->ui.cmbHosts->currentIndex(); if (i == -1) { return; } i = d->ui.cmbHosts->itemData(i).toInt(); const VPNHost &host = d->hosts.at(i); if (openconnect_parse_url(d->vpninfo, host.address.toLatin1().data())) { qCWarning(PLASMA_NM) << "Failed to parse server URL" << host.address; openconnect_set_hostname(d->vpninfo, OC3DUP(host.address.toLatin1().data())); } if (!openconnect_get_urlpath(d->vpninfo) && !host.group.isEmpty()) { openconnect_set_urlpath(d->vpninfo, OC3DUP(host.group.toLatin1().data())); } d->secrets["lasthost"] = host.name; addFormInfo(QLatin1String("dialog-information"), i18n("Contacting host, please wait...")); d->worker->start(); } void OpenconnectAuthWidget::initTokens() { Q_D(OpenconnectAuthWidget); if (d->token.tokenMode != OC_TOKEN_MODE_NONE) { __openconnect_set_token_mode(d->vpninfo, d->token.tokenMode, d->token.tokenSecret); } } QVariantMap OpenconnectAuthWidget::setting() const { Q_D(const OpenconnectAuthWidget); NMStringMap secrets; QVariantMap secretData; secrets.unite(d->secrets); QString host(openconnect_get_hostname(d->vpninfo)); const QString port = QString::number(openconnect_get_port(d->vpninfo)); secrets.insert(QLatin1String(NM_OPENCONNECT_KEY_GATEWAY), host + ':' + port); secrets.insert(QLatin1String(NM_OPENCONNECT_KEY_COOKIE), QLatin1String(openconnect_get_cookie(d->vpninfo))); openconnect_clear_cookie(d->vpninfo); #if OPENCONNECT_CHECK_VER(5,0) const char *fingerprint = openconnect_get_peer_cert_hash(d->vpninfo); #else OPENCONNECT_X509 *cert = openconnect_get_peer_cert(d->vpninfo); char fingerprint[41]; openconnect_get_cert_sha1(d->vpninfo, cert, fingerprint); #endif secrets.insert(QLatin1String(NM_OPENCONNECT_KEY_GWCERT), QLatin1String(fingerprint)); secrets.insert(QLatin1String("autoconnect"), d->ui.chkAutoconnect->isChecked() ? "yes" : "no"); secrets.insert(QLatin1String("save_passwords"), d->ui.chkStorePasswords->isChecked() ? "yes" : "no"); NMStringMap::iterator i = secrets.begin(); while (i != secrets.end()) { if (i.value().isEmpty()) { i = secrets.erase(i); } else { i++; } } secretData.insert("secrets", QVariant::fromValue(secrets)); // These secrets are not officially part of the secrets which would be returned back to NetworkManager. We just // need to somehow get them to our secret agent which will handle them separately and store them. if (!d->tmpSecrets.isEmpty()) { secretData.insert("tmp-secrets", QVariant::fromValue(d->tmpSecrets)); } return secretData; } #if OPENCONNECT_CHECK_VER(3,4) static int updateToken(void *cbdata, const char *tok) { NMStringMap *secrets = static_cast(cbdata); secrets->insert(QLatin1String(NM_OPENCONNECT_KEY_TOKEN_SECRET), QLatin1String(tok)); return 0; } #endif void OpenconnectAuthWidget::writeNewConfig(const QString & buf) { Q_D(OpenconnectAuthWidget); d->secrets["xmlconfig"] = buf; } void OpenconnectAuthWidget::updateLog(const QString &message, const int &level) { Q_D(OpenconnectAuthWidget); QPair pair; pair.first = message; if (pair.first.endsWith(QLatin1String("\n"))) { pair.first.chop(1); } switch (level) { case PRG_ERR: pair.second = OpenconnectAuthWidgetPrivate::Error; break; case PRG_INFO: pair.second = OpenconnectAuthWidgetPrivate::Info; break; case PRG_DEBUG: pair.second = OpenconnectAuthWidgetPrivate::Debug; break; case PRG_TRACE: pair.second = OpenconnectAuthWidgetPrivate::Trace; break; } if (pair.second <= d->ui.cmbLogLevel->currentIndex()) { d->ui.serverLog->append(pair.first); } d->serverLog.append(pair); if (d->serverLog.size() > 100) { d->serverLog.removeFirst(); } } void OpenconnectAuthWidget::logLevelChanged(int newLevel) { Q_D(OpenconnectAuthWidget); d->ui.serverLog->clear(); QList >::const_iterator i; for (i = d->serverLog.constBegin(); i != d->serverLog.constEnd(); ++i) { QPair pair = *i; if(pair.second <= newLevel) { d->ui.serverLog->append(pair.first); } } } void OpenconnectAuthWidget::addFormInfo(const QString &iconName, const QString &message) { Q_D(OpenconnectAuthWidget); QHBoxLayout *layout = new QHBoxLayout(); QLabel *icon = new QLabel(this); QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); sizePolicy.setHorizontalStretch(0); sizePolicy.setVerticalStretch(0); sizePolicy.setHeightForWidth(icon->sizePolicy().hasHeightForWidth()); icon->setSizePolicy(sizePolicy); icon->setMinimumSize(QSize(16, 16)); icon->setMaximumSize(QSize(16, 16)); layout->addWidget(icon); QLabel *text = new QLabel(this); text->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); text->setWordWrap(true); layout->addWidget(text); icon->setPixmap(QIcon::fromTheme(iconName).pixmap(KIconLoader::SizeSmall)); text->setText(message); d->ui.loginBoxLayout->addLayout(layout); } void OpenconnectAuthWidget::processAuthForm(struct oc_auth_form *form) { Q_D(OpenconnectAuthWidget); deleteAllFromLayout(d->ui.loginBoxLayout); if (form->banner) { addFormInfo(QLatin1String("dialog-information"), form->banner); } if (form->message) { addFormInfo(QLatin1String("dialog-information"), form->message); } if (form->error) { addFormInfo(QLatin1String("dialog-error"), form->error); } struct oc_form_opt *opt; QFormLayout *layout = new QFormLayout(); QSizePolicy policy(QSizePolicy::Expanding, QSizePolicy::Fixed); bool focusSet = false; for (opt = form->opts; opt; opt = opt->next) { if (opt->type == OC_FORM_OPT_HIDDEN || IGNORE_OPT(opt)) { continue; } QLabel *text = new QLabel(this); text->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); text->setText(QString(opt->label)); QWidget *widget = nullptr; const QString key = QString("form:%1:%2").arg(QLatin1String(form->auth_id)).arg(QLatin1String(opt->name)); const QString value = d->secrets.value(key); if (opt->type == OC_FORM_OPT_PASSWORD || opt->type == OC_FORM_OPT_TEXT) { PasswordField *le = new PasswordField(this); le->setText(value); if (opt->type == OC_FORM_OPT_PASSWORD) { le->setPasswordModeEnabled(true); } if (!focusSet && le->text().isEmpty()) { le->setFocus(Qt::OtherFocusReason); focusSet = true; } widget = qobject_cast(le); } else if (opt->type == OC_FORM_OPT_SELECT) { QComboBox *cmb = new QComboBox(this); struct oc_form_opt_select *sopt = reinterpret_cast(opt); #if !OPENCONNECT_CHECK_VER(8,0) const QString protocol = d->setting->data()[NM_OPENCONNECT_KEY_PROTOCOL]; #endif for (int i = 0; i < sopt->nr_choices; i++) { cmb->addItem(QString::fromUtf8(FORMCHOICE(sopt, i)->label), QString::fromUtf8(FORMCHOICE(sopt, i)->name)); if (value == QString::fromUtf8(FORMCHOICE(sopt, i)->name)) { cmb->setCurrentIndex(i); #if !OPENCONNECT_CHECK_VER(8,0) if (protocol != QLatin1String("nc") && sopt == AUTHGROUP_OPT(form) && i != AUTHGROUP_SELECTION(form)) { #else if (sopt == AUTHGROUP_OPT(form) && i != AUTHGROUP_SELECTION(form)) { #endif QTimer::singleShot(0, this, &OpenconnectAuthWidget::formGroupChanged); } } } #if !OPENCONNECT_CHECK_VER(8,0) if (protocol != QLatin1String("nc") && sopt == AUTHGROUP_OPT(form)) { #else if (sopt == AUTHGROUP_OPT(form)) { #endif +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(cmb, QOverload::of(&QComboBox::currentIndexChanged), this, &OpenconnectAuthWidget::formGroupChanged); +#else + connect(cmb, QOverload::of(&QComboBox::currentIndexChanged), this, &OpenconnectAuthWidget::formGroupChanged); +#endif } widget = qobject_cast(cmb); } if (widget) { widget->setProperty("openconnect_opt", (quintptr)opt); widget->setSizePolicy(policy); layout->addRow(text, widget); } } d->ui.loginBoxLayout->addLayout(layout); d->passwordFormIndex = d->ui.loginBoxLayout->count() - 1; QDialogButtonBox *box = new QDialogButtonBox(this); QPushButton *btn = box->addButton(QDialogButtonBox::Ok); btn->setText(i18nc("Verb, to proceed with login", "Login")); btn->setDefault(true); d->ui.loginBoxLayout->addWidget(box); box->setProperty("openconnect_form", (quintptr)form); connect(box, &QDialogButtonBox::accepted, this, &OpenconnectAuthWidget::formLoginClicked); } void OpenconnectAuthWidget::validatePeerCert(const QString &fingerprint, const QString &peerCert, const QString &reason, bool *accepted) { Q_D(OpenconnectAuthWidget); 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); #if !OPENCONNECT_CHECK_VER(5,0) #define openconnect_check_peer_cert_hash(v,d) strcmp(d, fingerprint.toUtf8().data()) #endif if (openconnect_check_peer_cert_hash(d->vpninfo, value.toUtf8().data())) { QWidget *widget = new QWidget(); QVBoxLayout *verticalLayout; QHBoxLayout *horizontalLayout; QLabel *icon; QLabel *infoText; QTextBrowser *certificate; verticalLayout = new QVBoxLayout(widget); horizontalLayout = new QHBoxLayout(widget); icon = new QLabel(widget); QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); sizePolicy.setHorizontalStretch(0); sizePolicy.setVerticalStretch(0); sizePolicy.setHeightForWidth(icon->sizePolicy().hasHeightForWidth()); icon->setSizePolicy(sizePolicy); icon->setMinimumSize(QSize(48, 48)); icon->setMaximumSize(QSize(48, 48)); horizontalLayout->addWidget(icon); infoText = new QLabel(widget); infoText->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); horizontalLayout->addWidget(infoText); verticalLayout->addLayout(horizontalLayout); certificate = new QTextBrowser(widget); certificate->setTextInteractionFlags(Qt::TextSelectableByMouse); certificate->setOpenLinks(false); verticalLayout->addWidget(certificate); 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)); infoText->setWordWrap(true); certificate->setText(peerCert); QPointer dialog = new QDialog(this); dialog.data()->setWindowModality(Qt::WindowModal); dialog->setLayout(new QVBoxLayout); 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(buttons); const NMStringMap dataMap = d->setting->data(); buttons->button(QDialogButtonBox::Ok)->setEnabled(dataMap[NM_OPENCONNECT_KEY_PREVENT_INVALID_CERT] != "yes"); if(dialog.data()->exec() == QDialog::Accepted) { *accepted = true; } else { *accepted = false; } if (dialog) { dialog.data()->deleteLater(); } widget->deleteLater(); } else { *accepted = true; } if (*accepted) { d->secrets.insert(key, QString(fingerprint)); } d->mutex.lock(); d->workerWaiting.wakeAll(); d->mutex.unlock(); } void OpenconnectAuthWidget::formGroupChanged() { Q_D(OpenconnectAuthWidget); d->formGroupChanged = true; formLoginClicked(); } // Writes the user input from the form into the oc_auth_form structs we got from // libopenconnect, and wakes the worker thread up to try to log in and obtain a // cookie with this data void OpenconnectAuthWidget::formLoginClicked() { Q_D(OpenconnectAuthWidget); const int lastIndex = d->ui.loginBoxLayout->count() - 1; QLayout *layout = d->ui.loginBoxLayout->itemAt(d->passwordFormIndex)->layout(); struct oc_auth_form *form = (struct oc_auth_form *) d->ui.loginBoxLayout->itemAt(lastIndex)->widget()->property("openconnect_form").value(); for (int i = 0; i < layout->count(); i++) { QLayoutItem *item = layout->itemAt(i); QWidget *widget = item->widget(); if (widget && widget->property("openconnect_opt").isValid()) { struct oc_form_opt *opt = (struct oc_form_opt *) widget->property("openconnect_opt").value(); const QString key = QString("form:%1:%2").arg(QLatin1String(form->auth_id)).arg(QLatin1String(opt->name)); if (opt->type == OC_FORM_OPT_PASSWORD || opt->type == OC_FORM_OPT_TEXT) { PasswordField *le = qobject_cast(widget); QByteArray text = le->text().toUtf8(); openconnect_set_option_value(opt, text.data()); if (opt->type == OC_FORM_OPT_TEXT) { d->secrets.insert(key, le->text()); } else { d->tmpSecrets.insert(key, le->text()); } } else if (opt->type == OC_FORM_OPT_SELECT) { QComboBox *cbo = qobject_cast(widget); QByteArray text = cbo->itemData(cbo->currentIndex()).toString().toLatin1(); openconnect_set_option_value(opt, text.data()); d->secrets.insert(key,cbo->itemData(cbo->currentIndex()).toString()); } } } deleteAllFromLayout(d->ui.loginBoxLayout); d->workerWaiting.wakeAll(); } void OpenconnectAuthWidget::workerFinished(const int &ret) { Q_D(OpenconnectAuthWidget); if (ret < 0) { QString message; QList >::const_iterator i; for (i = d->serverLog.constEnd()-1; i >= d->serverLog.constBegin(); --i) { QPair pair = *i; if(pair.second <= OpenconnectAuthWidgetPrivate::Error) { message = pair.first; break; } } if (message.isEmpty()) { message = i18n("Connection attempt was unsuccessful."); } deleteAllFromLayout(d->ui.loginBoxLayout); addFormInfo(QLatin1String("dialog-error"), message); } else { deleteAllFromLayout(d->ui.loginBoxLayout); acceptDialog(); } } void OpenconnectAuthWidget::deleteAllFromLayout(QLayout *layout) { while (QLayoutItem *item = layout->takeAt(0)) { if (QLayout *itemLayout = item->layout()) { deleteAllFromLayout(itemLayout); itemLayout->deleteLater(); } else { item->widget()->deleteLater(); } delete item; } layout->invalidate(); } void OpenconnectAuthWidget::viewServerLogToggled(bool toggled) { Q_D(OpenconnectAuthWidget); d->ui.lblLogLevel->setVisible(toggled); d->ui.cmbLogLevel->setVisible(toggled); if (toggled) { delete d->ui.verticalLayout->takeAt(5); QSizePolicy policy = d->ui.serverLogBox->sizePolicy(); policy.setVerticalPolicy(QSizePolicy::Expanding); d->ui.serverLogBox->setSizePolicy(policy); d->ui.serverLog->setVisible(true); } else { QSpacerItem *verticalSpacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); d->ui.verticalLayout->addItem(verticalSpacer); d->ui.serverLog->setVisible(false); QSizePolicy policy = d->ui.serverLogBox->sizePolicy(); policy.setVerticalPolicy(QSizePolicy::Fixed); d->ui.serverLogBox->setSizePolicy(policy); } } diff --git a/vpn/openconnect/openconnectwidget.cpp b/vpn/openconnect/openconnectwidget.cpp index 9d8e7963..0823b58f 100644 --- a/vpn/openconnect/openconnectwidget.cpp +++ b/vpn/openconnect/openconnectwidget.cpp @@ -1,340 +1,344 @@ /* Copyright 2011 Ilia Kats Copyright 2013 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "openconnectwidget.h" #include #include #include #include "ui_openconnectprop.h" #include "ui_openconnecttoken.h" #include #include #include "nm-openconnect-service.h" #include #ifndef OPENCONNECT_CHECK_VER #define OPENCONNECT_CHECK_VER(x,y) 0 #endif #if !OPENCONNECT_CHECK_VER(2,1) #define openconnect_has_stoken_support() 0 #endif #if !OPENCONNECT_CHECK_VER(2,2) #define openconnect_has_oath_support() 0 #endif #if !OPENCONNECT_CHECK_VER(5,0) #define openconnect_has_yubioath_support() 0 #endif typedef struct { int tokenIndex; QString tokenSecret; } Token; class OpenconnectSettingWidgetPrivate { public: Ui_OpenconnectProp ui; Ui::OpenConnectToken tokenUi; NetworkManager::VpnSetting::Ptr setting; QDialog *tokenDlg; Token token; }; OpenconnectSettingWidget::OpenconnectSettingWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget * parent) : SettingWidget(setting, parent) , d_ptr(new OpenconnectSettingWidgetPrivate) { Q_D(OpenconnectSettingWidget); d->ui.setupUi(this); d->setting = setting; // Connect for validity check connect(d->ui.leGateway, &QLineEdit::textChanged, this, &OpenconnectSettingWidget::slotWidgetChanged); connect(d->ui.buTokens, &QPushButton::clicked, this, &OpenconnectSettingWidget::showTokens); d->tokenDlg = new QDialog(this); d->tokenUi.setupUi(d->tokenDlg); d->tokenUi.leTokenSecret->setPasswordModeEnabled(true); d->tokenUi.leTokenSecret->setPasswordOptionsEnabled(true); QVBoxLayout * layout = new QVBoxLayout(d->tokenDlg); layout->addWidget(d->tokenDlg); d->tokenDlg->setLayout(layout); connect(d->tokenUi.buttonBox, &QDialogButtonBox::accepted, d->tokenDlg, &QDialog::accept); connect(d->tokenUi.buttonBox, &QDialogButtonBox::rejected, d->tokenDlg, &QDialog::reject); connect(d->tokenDlg, &QDialog::rejected, this, &OpenconnectSettingWidget::restoreTokens); connect(d->tokenDlg, &QDialog::accepted, this, &OpenconnectSettingWidget::saveTokens); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(d->tokenUi.cmbTokenMode, QOverload::of(&QComboBox::currentIndexChanged), this, QOverload::of((&OpenconnectSettingWidget::handleTokenSecret))); +#else + connect(d->tokenUi.cmbTokenMode, QOverload::of(&QComboBox::currentIndexChanged), this, QOverload::of((&OpenconnectSettingWidget::handleTokenSecret))); +#endif // Connect for setting check watchChangedSetting(); // Remove these from setting check: // Just popping up the tokenDlg changes nothing disconnect(d->ui.buTokens, &QPushButton::clicked, this, &SettingWidget::settingChanged); // User cancels means nothing should change here disconnect(d->tokenUi.buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &SettingWidget::settingChanged); d->tokenUi.gbToken->setVisible(initTokenGroup()); KAcceleratorManager::manage(this); if (d->setting) { loadConfig(d->setting); } } OpenconnectSettingWidget::~OpenconnectSettingWidget() { delete d_ptr; } void OpenconnectSettingWidget::handleTokenSecret(int index) { Q_D(const OpenconnectSettingWidget); QVariant mode = d->tokenUi.cmbTokenMode->itemData(index); if (mode == QStringLiteral("disabled")) { d->tokenUi.leTokenSecret->setEnabled(false); d->tokenUi.leTokenSecret->setToolTip("No secrets needed."); } else if (mode == QStringLiteral("stokenrc")) { d->tokenUi.leTokenSecret->setEnabled(false); d->tokenUi.leTokenSecret->setToolTip("No secrets needed; will read them from ~/.stokenrc."); } else if (mode == QStringLiteral("manual")) { d->tokenUi.leTokenSecret->setToolTip("Insert the secret here. See the openconnect documentation for syntax."); d->tokenUi.leTokenSecret->setEnabled(true); } else if (mode == QStringLiteral("totp")) { d->tokenUi.leTokenSecret->setEnabled(true); d->tokenUi.leTokenSecret->setToolTip("Insert the secret here, with a sha specification and a leading '0x' or 'base32:'. See the openconnect documentation for syntax."); } else if (mode ==QStringLiteral("hotp")) { d->tokenUi.leTokenSecret->setEnabled(true); d->tokenUi.leTokenSecret->setToolTip("Insert the secret here, with a leading '0x' or 'base32:' and a trailing counter after a comma (','), See the openconnect documentation for syntax."); } else if (mode == QStringLiteral("yubioath")) { d->tokenUi.leTokenSecret->setEnabled(true); d->tokenUi.leTokenSecret->setToolTip("Insert the token Id here, in the form company:username. Make sure to set your Yubikey in CCID mode"); } else { // Not really needed now, but who knows? d->tokenUi.leTokenSecret->setEnabled(false); d->tokenUi.leTokenSecret->setToolTip(""); } } bool OpenconnectSettingWidget::initTokenGroup() { Q_D(const OpenconnectSettingWidget); int validRows = 0; QStringList tokenLabelList = QStringList() << "Disabled" << "RSA SecurID — read from ~/.stokenrc" << "RSA SecurID — manually entered" << "TOTP — manually entered" << "HOTP — manually entered" << "Yubikey"; QStringList tokenModeList = QStringList() << "disabled" << "stokenrc" << "manual" << "totp" << "hotp" << "yubioath"; QComboBox *combo = d->tokenUi.cmbTokenMode; combo->addItem(tokenLabelList[validRows]); combo->setItemData(validRows, tokenModeList[validRows], Qt::UserRole); validRows++; if (openconnect_has_stoken_support ()) { for ( ; validRows < 3; validRows++) { combo->addItem(tokenLabelList[validRows]); combo->setItemData(validRows, tokenModeList[validRows], Qt::UserRole); } } if (openconnect_has_oath_support ()) { combo->addItem(tokenLabelList[validRows]); combo->setItemData(validRows, tokenModeList[validRows], Qt::UserRole); validRows++; if (OPENCONNECT_CHECK_VER(3,4)) { combo->addItem(tokenLabelList[validRows]); combo->setItemData(validRows, tokenModeList[validRows], Qt::UserRole); validRows++; } } if (openconnect_has_yubioath_support ()) { combo->addItem(tokenLabelList[validRows]); combo->setItemData(validRows, tokenModeList[validRows], Qt::UserRole); } return validRows > 0; } void OpenconnectSettingWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { Q_D(OpenconnectSettingWidget); // General settings const NMStringMap dataMap = setting.staticCast()->data(); int cmbProtocolIndex; if (dataMap[NM_OPENCONNECT_KEY_PROTOCOL] == QLatin1String("anyconnect")) { cmbProtocolIndex = 0; } else if (dataMap[NM_OPENCONNECT_KEY_PROTOCOL] == QLatin1String("nc")) { cmbProtocolIndex = 1; } else { cmbProtocolIndex = 2; // paloAlto/GlobalProtect (gp) } d->ui.cmbProtocol->setCurrentIndex(cmbProtocolIndex); d->ui.leGateway->setText(dataMap[NM_OPENCONNECT_KEY_GATEWAY]); d->ui.leCaCertificate->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENCONNECT_KEY_CACERT])); d->ui.leProxy->setText(dataMap[NM_OPENCONNECT_KEY_PROXY]); d->ui.chkAllowTrojan->setChecked(dataMap[NM_OPENCONNECT_KEY_CSD_ENABLE] == "yes"); d->ui.leCsdWrapperScript->setUrl(QUrl::fromLocalFile(dataMap[NM_OPENCONNECT_KEY_CSD_WRAPPER])); 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"); d->ui.preventInvalidCert->setChecked(dataMap[NM_OPENCONNECT_KEY_PREVENT_INVALID_CERT] == "yes"); // Token settings const NetworkManager::Setting::SecretFlags tokenSecretFlag = static_cast(dataMap.value(NM_OPENCONNECT_KEY_TOKEN_SECRET"-flags").toInt()); if (tokenSecretFlag == NetworkManager::Setting::None) { d->tokenUi.leTokenSecret->setPasswordOption(PasswordField::StoreForAllUsers); } else if (tokenSecretFlag == NetworkManager::Setting::AgentOwned) { d->tokenUi.leTokenSecret->setPasswordOption(PasswordField::StoreForUser); } else { d->tokenUi.leTokenSecret->setPasswordOption(PasswordField::AlwaysAsk); } for (int index = 0; index < d->tokenUi.cmbTokenMode->count(); index++) { if (d->tokenUi.cmbTokenMode->itemData(index, Qt::UserRole) == dataMap[NM_OPENCONNECT_KEY_TOKEN_MODE]) { d->tokenUi.cmbTokenMode->setCurrentIndex(index); d->token.tokenIndex = index; if (index > 1) { loadSecrets(d->setting); } break; } } } void OpenconnectSettingWidget::loadSecrets(const NetworkManager::Setting::Ptr &setting) { Q_D(OpenconnectSettingWidget); NetworkManager::VpnSetting::Ptr vpnSetting = setting.staticCast(); if (vpnSetting) { const NMStringMap secrets = vpnSetting->secrets(); d->tokenUi.leTokenSecret->setText(secrets.value(NM_OPENCONNECT_KEY_TOKEN_SECRET)); d->token.tokenSecret = secrets.value(NM_OPENCONNECT_KEY_TOKEN_SECRET); } } QVariantMap OpenconnectSettingWidget::setting() const { Q_D(const OpenconnectSettingWidget); NetworkManager::VpnSetting setting; setting.setServiceType(QLatin1String(NM_DBUS_SERVICE_OPENCONNECT)); NMStringMap data; NMStringMap secrets; QString protocol; switch (d->ui.cmbProtocol->currentIndex()) { case 0: protocol = QLatin1String("anyconnect"); break; case 1: protocol = QLatin1String("nc"); break; default: protocol = QLatin1String("gp"); } data.insert(NM_OPENCONNECT_KEY_PROTOCOL, protocol); data.insert(QLatin1String(NM_OPENCONNECT_KEY_GATEWAY), d->ui.leGateway->text()); if (d->ui.leCaCertificate->url().isValid()) { data.insert(QLatin1String(NM_OPENCONNECT_KEY_CACERT), d->ui.leCaCertificate->url().toLocalFile()); } if (!d->ui.leProxy->text().isEmpty()) { data.insert(QLatin1String(NM_OPENCONNECT_KEY_PROXY), d->ui.leProxy->text()); } data.insert(QLatin1String(NM_OPENCONNECT_KEY_CSD_ENABLE), d->ui.chkAllowTrojan->isChecked() ? "yes" : "no"); if (d->ui.leCsdWrapperScript->url().isValid()) { data.insert(QLatin1String(NM_OPENCONNECT_KEY_CSD_WRAPPER), d->ui.leCsdWrapperScript->url().toLocalFile()); } if (d->ui.leUserCert->url().isValid()) { data.insert(QLatin1String(NM_OPENCONNECT_KEY_USERCERT), d->ui.leUserCert->url().toLocalFile()); } if (d->ui.leUserPrivateKey->url().isValid()) { data.insert(QLatin1String(NM_OPENCONNECT_KEY_PRIVKEY), d->ui.leUserPrivateKey->url().toLocalFile()); } data.insert(QLatin1String(NM_OPENCONNECT_KEY_PEM_PASSPHRASE_FSID), d->ui.chkUseFsid->isChecked() ? "yes" : "no"); data.insert(QLatin1String(NM_OPENCONNECT_KEY_PREVENT_INVALID_CERT), d->ui.preventInvalidCert->isChecked() ? "yes" : "no"); int index = d->tokenUi.cmbTokenMode->currentIndex(); data.insert(QLatin1String(NM_OPENCONNECT_KEY_TOKEN_MODE), d->tokenUi.cmbTokenMode->itemData(index, Qt::UserRole).toString()); secrets.insert(QLatin1String(NM_OPENCONNECT_KEY_TOKEN_SECRET), d->tokenUi.leTokenSecret->text()); // Restore previous flags, this is necessary for keeping secrets stored in KWallet for (const QString &key : d->setting->data().keys()) { if (key.contains(QLatin1String("-flags"))) { data.insert(key, d->setting->data().value(key)); } } if (d->tokenUi.leTokenSecret->passwordOption() == PasswordField::StoreForAllUsers) { data.insert(NM_OPENCONNECT_KEY_TOKEN_SECRET"-flags", QString::number(NetworkManager::Setting::None)); } else if (d->tokenUi.leTokenSecret->passwordOption() == PasswordField::StoreForUser) { data.insert(NM_OPENCONNECT_KEY_TOKEN_SECRET"-flags", QString::number(NetworkManager::Setting::AgentOwned)); } else { data.insert(NM_OPENCONNECT_KEY_TOKEN_SECRET"-flags", QString::number(NetworkManager::Setting::NotSaved)); } /* These are different for every login session, and should not be stored */ data.insert(QLatin1String(NM_OPENCONNECT_KEY_COOKIE"-flags"), QString::number(NetworkManager::Setting::NotSaved)); data.insert(QLatin1String(NM_OPENCONNECT_KEY_GWCERT"-flags"), QString::number(NetworkManager::Setting::NotSaved)); data.insert(QLatin1String(NM_OPENCONNECT_KEY_GATEWAY"-flags"), QString::number(NetworkManager::Setting::NotSaved)); setting.setData(data); setting.setSecrets(secrets); return setting.toMap(); } void OpenconnectSettingWidget::restoreTokens() { Q_D(const OpenconnectSettingWidget); d->tokenUi.cmbTokenMode->setCurrentIndex(d->token.tokenIndex); d->tokenUi.leTokenSecret->setText(d->token.tokenSecret); } void OpenconnectSettingWidget::saveTokens() { Q_D(OpenconnectSettingWidget); d->token.tokenIndex = d->tokenUi.cmbTokenMode->currentIndex(); d->token.tokenSecret = d->tokenUi.leTokenSecret->text(); } void OpenconnectSettingWidget::showTokens() { Q_D(OpenconnectSettingWidget); d->tokenDlg->show(); } bool OpenconnectSettingWidget::isValid() const { Q_D(const OpenconnectSettingWidget); return !d->ui.leGateway->text().isEmpty(); } diff --git a/vpn/openvpn/openvpnadvancedwidget.cpp b/vpn/openvpn/openvpnadvancedwidget.cpp index 321a84d1..297c7df3 100644 --- a/vpn/openvpn/openvpnadvancedwidget.cpp +++ b/vpn/openvpn/openvpnadvancedwidget.cpp @@ -1,703 +1,715 @@ /* Copyright 2013 Lukas Tinkl Copyright 2015 Jan Grulich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "openvpnadvancedwidget.h" #include "ui_openvpnadvanced.h" #include "nm-openvpn-service.h" #include "settingwidget.h" #include #include #include #include #include #include class OpenVpnAdvancedWidget::Private { public: NetworkManager::VpnSetting::Ptr setting; KProcess *openvpnCipherProcess = nullptr; KProcess *openvpnVersionProcess = nullptr; QByteArray openvpnCiphers; QByteArray openVpnVersion; bool gotOpenVpnCiphers = false; bool gotOpenVpnVersion = false; bool readConfig = false; int versionX = 0; int versionY = 0; int versionZ = 0; class EnumProxyType { public: enum ProxyType {NotRequired = 0, HTTP = 1, SOCKS = 2}; }; class EnumHashingAlgorithms { public: enum HashingAlgorithms {Default = 0, None, Md4, Md5, Sha1, Sha224, Sha256, Sha384, Sha512, Ripemd160}; }; }; OpenVpnAdvancedWidget::OpenVpnAdvancedWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget *parent) : QDialog(parent) , m_ui(new Ui::OpenVpnAdvancedWidget) , d(new Private) { m_ui->setupUi(this); setWindowTitle(i18nc("@title: window advanced openvpn properties", "Advanced OpenVPN properties")); d->setting = setting; m_ui->proxyPassword->setPasswordOptionsEnabled(true); m_ui->proxyPassword->setPasswordNotRequiredEnabled(true); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->cbCertCheck, QOverload::of(&QComboBox::currentIndexChanged), this, &OpenVpnAdvancedWidget::certCheckTypeChanged); +#else + connect(m_ui->cbCertCheck, QOverload::of(&QComboBox::currentIndexChanged), this, &OpenVpnAdvancedWidget::certCheckTypeChanged); +#endif +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->cmbProxyType, QOverload::of(&QComboBox::currentIndexChanged), this, &OpenVpnAdvancedWidget::proxyTypeChanged); +#else + connect(m_ui->cmbProxyType, QOverload::of(&QComboBox::currentIndexChanged), this, &OpenVpnAdvancedWidget::proxyTypeChanged); +#endif +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(m_ui->cboTLSMode, QOverload::of(&QComboBox::currentIndexChanged), this, [this] (int index) { +#else + connect(m_ui->cboTLSMode, QOverload::of(&QComboBox::currentIndexChanged), this, [this] (int index) { +#endif if (index == 0) { m_ui->kurlTlsAuthKey->setDisabled(true); m_ui->cboDirection->setDisabled(true); } else if (index == 1) { // TLS-Auth m_ui->kurlTlsAuthKey->setEnabled(true); m_ui->cboDirection->setEnabled(true); } else { // TLS-Crypt m_ui->kurlTlsAuthKey->setEnabled(true); m_ui->cboDirection->setDisabled(true); } }); // start openVPN process and get its cipher list const QString openVpnBinary = QStandardPaths::findExecutable("openvpn", QStringList() << "/sbin" << "/usr/sbin"); const QStringList ciphersArgs(QLatin1String("--show-ciphers")); const QStringList versionArgs(QLatin1String("--version")); d->openvpnCipherProcess = new KProcess(this); d->openvpnCipherProcess->setOutputChannelMode(KProcess::OnlyStdoutChannel); d->openvpnCipherProcess->setReadChannel(QProcess::StandardOutput); connect(d->openvpnCipherProcess, &KProcess::errorOccurred, this, &OpenVpnAdvancedWidget::openVpnCipherError); connect(d->openvpnCipherProcess, &KProcess::readyReadStandardOutput, this, &OpenVpnAdvancedWidget::gotOpenVpnCipherOutput); connect(d->openvpnCipherProcess, QOverload::of(&KProcess::finished), this, &OpenVpnAdvancedWidget::openVpnCipherFinished); d->openvpnCipherProcess->setProgram(openVpnBinary, ciphersArgs); d->openvpnVersionProcess = new KProcess(this); d->openvpnVersionProcess->setOutputChannelMode(KProcess::OnlyStdoutChannel); d->openvpnVersionProcess->setReadChannel(QProcess::StandardOutput); connect(d->openvpnVersionProcess, &KProcess::errorOccurred, this, &OpenVpnAdvancedWidget::openVpnVersionError); connect(d->openvpnVersionProcess, &KProcess::readyReadStandardOutput, this, &OpenVpnAdvancedWidget::gotOpenVpnVersionOutput); connect(d->openvpnVersionProcess, QOverload::of(&KProcess::finished), this, &OpenVpnAdvancedWidget::openVpnVersionFinished); d->openvpnVersionProcess->setProgram(openVpnBinary, versionArgs); connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &OpenVpnAdvancedWidget::accept); connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &OpenVpnAdvancedWidget::reject); KAcceleratorManager::manage(this); if (d->setting) { loadConfig(); } } OpenVpnAdvancedWidget::~OpenVpnAdvancedWidget() { delete d; } void OpenVpnAdvancedWidget::init() { d->openvpnCipherProcess->start(); d->openvpnVersionProcess->start(); } void OpenVpnAdvancedWidget::gotOpenVpnCipherOutput() { d->openvpnCiphers.append(d->openvpnCipherProcess->readAll()); } void OpenVpnAdvancedWidget::openVpnCipherError(QProcess::ProcessError) { m_ui->cboCipher->removeItem(0); m_ui->cboCipher->addItem(i18nc("@item:inlistbox Item added when OpenVPN cipher lookup failed", "OpenVPN cipher lookup failed")); } void OpenVpnAdvancedWidget::openVpnCipherFinished(int exitCode, QProcess::ExitStatus exitStatus) { m_ui->cboCipher->removeItem(0); if (!exitCode && exitStatus == QProcess::NormalExit) { m_ui->cboCipher->addItem(i18nc("@item::inlist Default openvpn cipher item", "Default")); const QList rawOutputLines = d->openvpnCiphers.split('\n'); bool foundFirstSpace = false; for (const QByteArray &cipher : rawOutputLines) { if (cipher.length() == 0) { foundFirstSpace = true; } else if (foundFirstSpace) { m_ui->cboCipher->addItem(QString::fromLocal8Bit(cipher.left(cipher.indexOf(' ')))); } } if (m_ui->cboCipher->count()) { m_ui->cboCipher->setEnabled(true); } else { m_ui->cboCipher->addItem(i18nc("@item:inlistbox Item added when OpenVPN cipher lookup failed", "No OpenVPN ciphers found")); } } else { m_ui->cboCipher->addItem(i18nc("@item:inlistbox Item added when OpenVPN cipher lookup failed", "OpenVPN cipher lookup failed")); } delete d->openvpnCipherProcess; d->openvpnCipherProcess = nullptr; d->openvpnCiphers = QByteArray(); d->gotOpenVpnCiphers = true; if (d->readConfig) { const NMStringMap dataMap = d->setting->data(); if (dataMap.contains(NM_OPENVPN_KEY_CIPHER)) { m_ui->cboCipher->setCurrentIndex(m_ui->cboCipher->findText(dataMap.value(NM_OPENVPN_KEY_CIPHER))); } } } void OpenVpnAdvancedWidget::gotOpenVpnVersionOutput() { d->openVpnVersion.append(d->openvpnVersionProcess->readAll()); } void OpenVpnAdvancedWidget::openVpnVersionError(QProcess::ProcessError) { // We couldn't identify OpenVPN version so disable tls-remote disableLegacySubjectMatch(); } void OpenVpnAdvancedWidget::openVpnVersionFinished(int exitCode, QProcess::ExitStatus exitStatus) { // OpenVPN returns 1 when you use "--help" and unfortunately returns 1 even when some error occurs if (exitCode == 1 && exitStatus == QProcess::NormalExit) { QStringList list = QString(d->openVpnVersion).split(QLatin1Char(' ')); if (list.count() > 2) { const QStringList versionList = list.at(1).split(QLatin1Char('.')); if (versionList.count() == 3) { d->versionX = versionList.at(0).toInt(); d->versionY = versionList.at(1).toInt(); d->versionZ = versionList.at(2).toInt(); if (compareVersion(2, 4, 0) >= 0) { disableLegacySubjectMatch(); } } } } else { disableLegacySubjectMatch(); } delete d->openvpnVersionProcess; d->openvpnVersionProcess = nullptr; d->openVpnVersion = QByteArray(); d->gotOpenVpnVersion = true; if (d->readConfig) { const NMStringMap dataMap = d->setting->data(); if (dataMap.contains(NM_OPENVPN_KEY_TLS_REMOTE)) { m_ui->subjectMatch->setText(dataMap.value(NM_OPENVPN_KEY_TLS_REMOTE)); } } } int OpenVpnAdvancedWidget::compareVersion(const int x, const int y, const int z) const { if (d->versionX == 0) { // Not valid version return -2; } if (d->versionX > x) { return 1; } else if (d->versionX < x) { return -1; } else if (d->versionY > y) { return 1; } else if (d->versionY < y) { return -1; } else if (d->versionZ > z) { return 1; } else if (d->versionZ < z) { return -1; } return 0; } void OpenVpnAdvancedWidget::disableLegacySubjectMatch() { m_ui->cbCertCheck->removeItem(CertCheckType::VerifySubjectPartially); } void OpenVpnAdvancedWidget::loadConfig() { const NMStringMap dataMap = d->setting->data(); const NMStringMap secrets = d->setting->secrets(); // Optional Settings if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PORT))) { m_ui->chkCustomPort->setChecked(true); m_ui->sbCustomPort->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PORT)].toUInt()); } else { m_ui->chkCustomPort->setChecked(false); m_ui->sbCustomPort->setValue(1194); // Default value } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_TUNNEL_MTU))) { m_ui->chkMtu->setChecked(true); m_ui->sbMtu->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_TUNNEL_MTU)].toUInt()); } else { m_ui->chkMtu->setChecked(false); m_ui->sbMtu->setValue(1500); // Default value } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_FRAGMENT_SIZE))) { m_ui->chkCustomFragmentSize->setChecked(true); m_ui->sbCustomFragmentSize->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_FRAGMENT_SIZE)].toUInt()); } else { m_ui->chkCustomFragmentSize->setChecked(false); m_ui->sbCustomFragmentSize->setValue(1300); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_RENEG_SECONDS))) { m_ui->chkUseCustomReneg->setChecked(true); m_ui->sbCustomReneg->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_RENEG_SECONDS)].toUInt()); } else { m_ui->chkUseCustomReneg->setChecked(false); m_ui->sbCustomReneg->setValue(0); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_COMP_LZO))) { const QString compLzo = dataMap[QLatin1String(NM_OPENVPN_KEY_COMP_LZO)]; if (compLzo == QLatin1String("no-by-default")) { m_ui->cmbUseLZO->setCurrentIndex(0); } else if (compLzo == QLatin1String("yes")) { m_ui->cmbUseLZO->setCurrentIndex(1); } else { m_ui->cmbUseLZO->setCurrentIndex(2); } m_ui->chkUseLZO->setChecked(true); } m_ui->chkUseTCP->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_PROTO_TCP)] == QLatin1String("yes")); if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_DEV_TYPE))) { m_ui->chkUseVirtualDeviceType->setChecked(true); if (dataMap[QLatin1String(NM_OPENVPN_KEY_DEV_TYPE)] == QLatin1String("tap")) { m_ui->cmbDeviceType->setCurrentIndex(1); } } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_DEV))) { m_ui->chkUseVirtualDeviceName->setChecked(true); m_ui->leVirtualDeviceName->setText(dataMap[QLatin1String(NM_OPENVPN_KEY_DEV)]); } m_ui->chkMssRestrict->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_MSSFIX)] == QLatin1String("yes")); m_ui->chkRandRemHosts->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_REMOTE_RANDOM)] == QLatin1String("yes")); m_ui->chkIpv6TunLink->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_TUN_IPV6)] == QLatin1String("yes")); if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PING))) { m_ui->chkPingInterval->setChecked(true); m_ui->sbPingInterval->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PING)].toInt()); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PING_EXIT)) || dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PING_RESTART))) { m_ui->chkSpecifyExitRestartPing->setChecked(true); if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PING_EXIT))) { m_ui->cbSpecifyExitRestartPing->setCurrentIndex(0); // Exit m_ui->sbSpecifyExitRestartPing->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PING_EXIT)].toInt()); } else { m_ui->cbSpecifyExitRestartPing->setCurrentIndex(1); // Restart m_ui->sbSpecifyExitRestartPing->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PING_RESTART)].toInt()); } } m_ui->chkAcceptAuthenticatedPackets->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_FLOAT)] == QLatin1String("yes")); if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_MAX_ROUTES))) { m_ui->chkMaxRoutes->setChecked(true); m_ui->sbMaxRoutes->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_MAX_ROUTES)].toInt()); } // Optional Security Settings const QString hmacKeyAuth = dataMap[QLatin1String(NM_OPENVPN_KEY_AUTH)]; if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_NONE)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::None); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_RSA_MD4)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Md4); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_MD5)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Md5); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA1)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha1); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA224)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha224); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA256)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha256); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA384)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha384); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA512)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha512); } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_RIPEMD160)) { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Ripemd160); } else { m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Default); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_KEYSIZE))) { m_ui->chkUseCustomCipherKey->setChecked(true); m_ui->sbCustomCipherKey->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_KEYSIZE)].toUInt()); } // ciphers populated above? if (d->gotOpenVpnCiphers && dataMap.contains(QLatin1String(NM_OPENVPN_KEY_CIPHER))) { m_ui->cboCipher->setCurrentIndex(m_ui->cboCipher->findText(dataMap[QLatin1String(NM_OPENVPN_KEY_CIPHER)])); } // Optional TLS if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_TLS_REMOTE))) { m_ui->cbCertCheck->setCurrentIndex(CertCheckType::VerifySubjectPartially); m_ui->subjectMatch->setText(dataMap[QLatin1String(NM_OPENVPN_KEY_TLS_REMOTE)]); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME))) { const QString x509Value = dataMap.value(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME)); const QStringList x509List = x509Value.split(QLatin1Char(':')); if (x509List.size() == 2) { if (x509List.at(0) == QLatin1String(NM_OPENVPN_VERIFY_X509_NAME_TYPE_SUBJECT)) { m_ui->cbCertCheck->setCurrentIndex(CertCheckType::VerifyWholeSubjectExactly); } else if (x509List.at(0) == QLatin1String(NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME)) { m_ui->cbCertCheck->setCurrentIndex(CertCheckType::VerifyNameExactly); } else if (x509List.at(0) == QLatin1String(NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME_PREFIX)) { m_ui->cbCertCheck->setCurrentIndex(CertCheckType::VerifyNameByPrefix); } m_ui->subjectMatch->setText(x509List.at(1)); } } else { m_ui->cbCertCheck->setCurrentIndex(CertCheckType::DontVerify); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_REMOTE_CERT_TLS))) { const QString remoteCertTls = dataMap[QLatin1String(NM_OPENVPN_KEY_REMOTE_CERT_TLS)]; m_ui->chkRemoteCertTls->setChecked(true); m_ui->labelRemoteCertTls->setEnabled(true); m_ui->cmbRemoteCertTls->setEnabled(true); m_ui->cmbRemoteCertTls->setCurrentIndex(remoteCertTls == QLatin1String(NM_OPENVPN_REM_CERT_TLS_SERVER) ? 0 : 1); } if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_NS_CERT_TYPE))) { const QString remoteCertTls = dataMap[QLatin1String(NM_OPENVPN_KEY_NS_CERT_TYPE)]; m_ui->chkNsCertType->setChecked(true); m_ui->lblNsCertType->setEnabled(true); m_ui->cmbNsCertType->setEnabled(true); m_ui->cmbNsCertType->setCurrentIndex(remoteCertTls == QLatin1String(NM_OPENVPN_NS_CERT_TYPE_SERVER) ? 0 : 1); } const QString openvpnKeyTa = dataMap[QLatin1String(NM_OPENVPN_KEY_TA)]; const QString openvpnKeyTlsCrypt = dataMap[QLatin1String(NM_OPENVPN_KEY_TLS_CRYPT)]; if (!openvpnKeyTlsCrypt.isEmpty()) { m_ui->cboTLSMode->setCurrentIndex(2); // TLS-Crypt m_ui->kurlTlsAuthKey->setUrl(QUrl::fromLocalFile(openvpnKeyTlsCrypt)); } else if (!openvpnKeyTa.isEmpty()) { m_ui->cboTLSMode->setCurrentIndex(1); // TLS-Auth m_ui->kurlTlsAuthKey->setUrl(QUrl::fromLocalFile(openvpnKeyTa)); if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_TA_DIR))) { const uint tlsAuthDirection = dataMap[QLatin1String(NM_OPENVPN_KEY_TA_DIR)].toUInt(); m_ui->cboDirection->setCurrentIndex(tlsAuthDirection + 1); } } // Proxies if (dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_TYPE)] == QLatin1String("http")) { m_ui->cmbProxyType->setCurrentIndex(Private::EnumProxyType::HTTP); } else if (dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_TYPE)] == QLatin1String("socks")) { m_ui->cmbProxyType->setCurrentIndex(Private::EnumProxyType::SOCKS); } else { m_ui->cmbProxyType->setCurrentIndex(Private::EnumProxyType::NotRequired); } proxyTypeChanged(m_ui->cmbProxyType->currentIndex()); m_ui->proxyServerAddress->setText(dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_SERVER)]); if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PROXY_PORT))) { m_ui->sbProxyPort->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_PORT)].toUInt()); } else { m_ui->sbProxyPort->setValue(0); } m_ui->chkProxyRetry->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_RETRY)] == QLatin1String("yes")); m_ui->proxyUsername->setText(dataMap[QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_USERNAME)]); d->readConfig = true; NetworkManager::Setting::SecretFlags type; type = (NetworkManager::Setting::SecretFlags)dataMap[NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD"-flags"].toInt(); if (!(type & NetworkManager::Setting::NotSaved || type & NetworkManager::Setting::NotRequired)) { m_ui->proxyPassword->setText(secrets.value(QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD))); } fillOnePasswordCombo(m_ui->proxyPassword, type); } void OpenVpnAdvancedWidget::fillOnePasswordCombo(PasswordField *passwordField, NetworkManager::Setting::SecretFlags type) { if (type.testFlag(NetworkManager::Setting::None)) { passwordField->setPasswordOption(PasswordField::StoreForAllUsers); } else if (type.testFlag(NetworkManager::Setting::AgentOwned)) { passwordField->setPasswordOption(PasswordField::StoreForUser); } else if (type.testFlag(NetworkManager::Setting::NotSaved)) { passwordField->setPasswordOption(PasswordField::AlwaysAsk); } else { passwordField->setPasswordOption(PasswordField::PasswordField::NotRequired); } } NetworkManager::VpnSetting::Ptr OpenVpnAdvancedWidget::setting() const { NMStringMap data; NMStringMap secretData; // optional settings if (m_ui->chkCustomPort->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_PORT), QString::number(m_ui->sbCustomPort->value())); } if (m_ui->chkMtu->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_TUNNEL_MTU), QString::number(m_ui->sbMtu->value())); } if (m_ui->chkCustomFragmentSize->isChecked() ) { data.insert(QLatin1String(NM_OPENVPN_KEY_FRAGMENT_SIZE), QString::number(m_ui->sbCustomFragmentSize->value())); } if (m_ui->chkUseCustomReneg->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_RENEG_SECONDS), QString::number(m_ui->sbCustomReneg->value())); } data.insert(QLatin1String(NM_OPENVPN_KEY_PROTO_TCP), m_ui->chkUseTCP->isChecked() ? QLatin1String("yes") : QLatin1String("no")); if (m_ui->chkUseLZO->isChecked()) { switch (m_ui->cmbUseLZO->currentIndex()) { case 0: data.insert(QLatin1String(NM_OPENVPN_KEY_COMP_LZO), QLatin1String("no-by-default")); break; case 1: data.insert(QLatin1String(NM_OPENVPN_KEY_COMP_LZO), QLatin1String("yes")); break; case 2: data.insert(QLatin1String(NM_OPENVPN_KEY_COMP_LZO), QLatin1String("adaptive")); break; } } if (m_ui->chkUseVirtualDeviceType->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_DEV_TYPE), m_ui->cmbDeviceType->currentIndex() == 0 ? QLatin1String("tun") : QLatin1String("tap")); } if (m_ui->chkUseVirtualDeviceName->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_DEV), m_ui->leVirtualDeviceName->text()); } data.insert(QLatin1String(NM_OPENVPN_KEY_MSSFIX), m_ui->chkMssRestrict->isChecked() ? QLatin1String("yes") : QLatin1String("no")); data.insert(QLatin1String(NM_OPENVPN_KEY_REMOTE_RANDOM), m_ui->chkRandRemHosts->isChecked() ? QLatin1String("yes") : QLatin1String("no")); data.insert(QLatin1String(NM_OPENVPN_KEY_TUN_IPV6), m_ui->chkIpv6TunLink->isChecked() ? QLatin1String("yes") : QLatin1String("no")); if (m_ui->chkPingInterval->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_PING), QString::number(m_ui->sbPingInterval->value())); } if (m_ui->chkSpecifyExitRestartPing->isChecked()) { if (m_ui->cbSpecifyExitRestartPing->currentIndex() == 0) { // Exit data.insert(QLatin1String(NM_OPENVPN_KEY_PING_EXIT), QString::number(m_ui->sbSpecifyExitRestartPing->value())); } else { // Restart data.insert(QLatin1String(NM_OPENVPN_KEY_PING_RESTART), QString::number(m_ui->sbSpecifyExitRestartPing->value())); } } data.insert(QLatin1String(NM_OPENVPN_KEY_FLOAT), m_ui->chkAcceptAuthenticatedPackets->isChecked() ? QLatin1String("yes") : QLatin1String("no")); if (m_ui->chkMaxRoutes->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_MAX_ROUTES), QString::number(m_ui->sbMaxRoutes->value())); } // Optional Security switch (m_ui->cboHmac->currentIndex()) { case Private::EnumHashingAlgorithms::Default: break; case Private::EnumHashingAlgorithms::None: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_NONE)); break; case Private::EnumHashingAlgorithms::Md4: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_RSA_MD4)); break; case Private::EnumHashingAlgorithms::Md5: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_MD5)); break; case Private::EnumHashingAlgorithms::Sha1: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA1)); break; case Private::EnumHashingAlgorithms::Sha224: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA224)); break; case Private::EnumHashingAlgorithms::Sha256: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA256)); break; case Private::EnumHashingAlgorithms::Sha384: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA384)); break; case Private::EnumHashingAlgorithms::Sha512: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA512)); break; case Private::EnumHashingAlgorithms::Ripemd160: data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_RIPEMD160)); break; } if (m_ui->chkUseCustomCipherKey->isChecked()) { data.insert(QLatin1String(NM_OPENVPN_KEY_KEYSIZE), QString::number(m_ui->sbCustomCipherKey->value())); } if (m_ui->cboCipher->currentIndex() != 0) { data.insert(QLatin1String(NM_OPENVPN_KEY_CIPHER), m_ui->cboCipher->currentText()); } // optional tls authentication switch (m_ui->cbCertCheck->currentIndex()) { case CertCheckType::DontVerify: break; case CertCheckType::VerifyWholeSubjectExactly: data.insert(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME), QStringLiteral("%1:%2").arg(NM_OPENVPN_VERIFY_X509_NAME_TYPE_SUBJECT).arg(m_ui->subjectMatch->text())); break; case CertCheckType::VerifyNameExactly: data.insert(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME), QStringLiteral("%1:%2").arg(NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME).arg(m_ui->subjectMatch->text())); break; case CertCheckType::VerifyNameByPrefix: data.insert(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME), QStringLiteral("%1:%2").arg(NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME_PREFIX).arg(m_ui->subjectMatch->text())); break; case CertCheckType::VerifySubjectPartially: data.insert(QLatin1String(NM_OPENVPN_KEY_TLS_REMOTE), m_ui->subjectMatch->text()); break; } if (m_ui->chkRemoteCertTls->isChecked()) { if (m_ui->cmbRemoteCertTls->currentIndex() == 0) { data.insert(QLatin1String(NM_OPENVPN_KEY_REMOTE_CERT_TLS), NM_OPENVPN_REM_CERT_TLS_SERVER); } else { data.insert(QLatin1String(NM_OPENVPN_KEY_REMOTE_CERT_TLS), NM_OPENVPN_REM_CERT_TLS_CLIENT); } } if (m_ui->chkNsCertType->isChecked()) { if (m_ui->cmbNsCertType->currentIndex() == 0) { data.insert(QLatin1String(NM_OPENVPN_KEY_NS_CERT_TYPE), NM_OPENVPN_NS_CERT_TYPE_SERVER); } else { data.insert(QLatin1String(NM_OPENVPN_KEY_NS_CERT_TYPE), NM_OPENVPN_NS_CERT_TYPE_CLIENT); } } if (m_ui->cboTLSMode->currentIndex() == 1) { // TLS-Auth QUrl tlsAuthKeyUrl = m_ui->kurlTlsAuthKey->url(); if (!tlsAuthKeyUrl.isEmpty()) { data.insert(QLatin1String(NM_OPENVPN_KEY_TA), tlsAuthKeyUrl.path()); } if (m_ui->cboDirection->currentIndex() > 0) { data.insert(QLatin1String(NM_OPENVPN_KEY_TA_DIR), QString::number(m_ui->cboDirection->currentIndex() - 1)); } } else if (m_ui->cboTLSMode->currentIndex() == 2) { // TLS-Crypt QUrl tlsCryptKeyUrl = m_ui->kurlTlsAuthKey->url(); if (!tlsCryptKeyUrl.isEmpty()) { data.insert(QLatin1String(NM_OPENVPN_KEY_TLS_CRYPT), tlsCryptKeyUrl.path()); } } // Proxies switch (m_ui->cmbProxyType->currentIndex()) { case Private::EnumProxyType::NotRequired: break; case Private::EnumProxyType::HTTP: data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_TYPE), QLatin1String("http")); data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_SERVER), m_ui->proxyServerAddress->text()); data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_PORT), QString::number(m_ui->sbProxyPort->value())); data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_RETRY), m_ui->chkProxyRetry->isChecked() ? QLatin1String("yes") : QLatin1String("no")); if (!m_ui->proxyUsername->text().isEmpty()) { data.insert(QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_USERNAME), m_ui->proxyUsername->text()); secretData.insert(QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD), m_ui->proxyPassword->text()); handleOnePasswordType(m_ui->proxyPassword, QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD"-flags"), data); } break; case Private::EnumProxyType::SOCKS: data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_TYPE), QLatin1String("socks")); data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_SERVER), m_ui->proxyServerAddress->text()); data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_PORT), QString::number(m_ui->sbProxyPort->value())); data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_RETRY), m_ui->chkProxyRetry->isChecked() ? QLatin1String("yes") : QLatin1String("no")); break; } d->setting->setData(data); d->setting->setSecrets(secretData); return d->setting; } void OpenVpnAdvancedWidget::certCheckTypeChanged(int type) { if (type == CertCheckType::DontVerify) { m_ui->lbSubjectMatch->setEnabled(false); m_ui->subjectMatch->setEnabled(false); } else { m_ui->lbSubjectMatch->setEnabled(true); m_ui->subjectMatch->setEnabled(true); } } void OpenVpnAdvancedWidget::proxyTypeChanged(int type) { switch (type) { case Private::EnumProxyType::NotRequired: m_ui->proxyServerAddress->setEnabled(false); m_ui->sbProxyPort->setEnabled(false); m_ui->chkProxyRetry->setEnabled(false); m_ui->proxyUsername->setEnabled(false); m_ui->proxyPassword->setEnabled(false); break; case Private::EnumProxyType::HTTP: m_ui->proxyServerAddress->setEnabled(true); m_ui->sbProxyPort->setEnabled(true); m_ui->chkProxyRetry->setEnabled(true); m_ui->proxyUsername->setEnabled(true); m_ui->proxyPassword->setEnabled(true); break; case Private::EnumProxyType::SOCKS: m_ui->proxyServerAddress->setEnabled(true); m_ui->sbProxyPort->setEnabled(true); m_ui->chkProxyRetry->setEnabled(true); m_ui->proxyUsername->setEnabled(false); m_ui->proxyPassword->setEnabled(false); break; } } void OpenVpnAdvancedWidget::handleOnePasswordType(const PasswordField *passwordField, const QString & key, NMStringMap & data) const { const PasswordField::PasswordOption option = passwordField->passwordOption(); switch (option) { case PasswordField::StoreForAllUsers: data.insert(key, QString::number(NetworkManager::Setting::None)); break; case PasswordField::StoreForUser: data.insert(key, QString::number(NetworkManager::Setting::AgentOwned)); break; case PasswordField::AlwaysAsk: data.insert(key, QString::number(NetworkManager::Setting::NotSaved)); break; case PasswordField::NotRequired: data.insert(key, QString::number(NetworkManager::Setting::NotRequired)); break; } } diff --git a/vpn/ssh/sshwidget.cpp b/vpn/ssh/sshwidget.cpp index 9399a038..9a2187bc 100644 --- a/vpn/ssh/sshwidget.cpp +++ b/vpn/ssh/sshwidget.cpp @@ -1,394 +1,398 @@ /* Copyright 2015 Jan Grulich This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "sshwidget.h" #include "ui_sshwidget.h" #include "ui_sshadvanced.h" #include "simpleipv4addressvalidator.h" #include "simpleipv6addressvalidator.h" #include #include #include #include "nm-ssh-service.h" class SshSettingWidgetPrivate { public: Ui_SshWidget ui; Ui_SshAdvanced advUi; NetworkManager::VpnSetting::Ptr setting; QDialog *advancedDlg; QWidget *advancedWid; }; SshSettingWidget::SshSettingWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget *parent) : SettingWidget(setting, parent) , d_ptr(new SshSettingWidgetPrivate) { Q_D(SshSettingWidget); d->ui.setupUi(this); d->setting = setting; d->ui.le_password->setPasswordOptionsEnabled(true); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(d->ui.cmb_authType, QOverload::of(&QComboBox::currentIndexChanged), this, &SshSettingWidget::authTypeChanged); +#else + connect(d->ui.cmb_authType, QOverload::of(&QComboBox::currentIndexChanged), this, &SshSettingWidget::authTypeChanged); +#endif connect(d->ui.btn_advancedOption, &QPushButton::clicked, this, &SshSettingWidget::doAdvancedDialog); d->advancedDlg = new QDialog(this); d->advancedDlg->setModal(true); d->advancedWid = new QWidget(this); d->advUi.setupUi(d->advancedWid); QVBoxLayout *layout = new QVBoxLayout(d->advancedDlg); layout->addWidget(d->advancedWid); d->advancedDlg->setLayout(layout); QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, d->advancedDlg); connect(buttons, &QDialogButtonBox::accepted, d->advancedDlg, &QDialog::accept); connect(buttons, &QDialogButtonBox::rejected, d->advancedDlg, &QDialog::reject); layout->addWidget(buttons); // Connect for setting check watchChangedSetting(); // Connect for validity check connect(d->ui.le_gateway, &QLineEdit::textChanged, this, &SshSettingWidget::slotWidgetChanged); connect(d->ui.le_localIp, &QLineEdit::textChanged, this, &SshSettingWidget::slotWidgetChanged); connect(d->ui.le_netmask, &QLineEdit::textChanged, this, &SshSettingWidget::slotWidgetChanged); connect(d->ui.le_remoteIp, &QLineEdit::textChanged, this, &SshSettingWidget::slotWidgetChanged); SimpleIpV4AddressValidator *ipv4Validator = new SimpleIpV4AddressValidator(SimpleIpV4AddressValidator::Base, this); d->ui.le_localIp->setValidator(ipv4Validator); d->ui.le_remoteIp->setValidator(ipv4Validator); d->ui.le_netmask->setValidator(ipv4Validator); SimpleIpV6AddressValidator *ipv6Validator = new SimpleIpV6AddressValidator(SimpleIpV6AddressValidator::Base, this); d->ui.le_localIpv6->setValidator(ipv6Validator); d->ui.le_remoteIpv6->setValidator(ipv6Validator); d->ui.passwordWidget->setVisible(false); d->advUi.sb_useCustomGatewayPort->setValue(NM_SSH_DEFAULT_PORT); d->advUi.sb_useCustomTunnelMtu->setValue(NM_SSH_DEFAULT_MTU); d->advUi.le_extraSshOptions->setText(QLatin1String(NM_SSH_DEFAULT_EXTRA_OPTS)); d->advUi.sb_remoteDeviceNumber->setValue(NM_SSH_DEFAULT_REMOTE_DEV); d->advUi.le_remoteUsername->setText(QLatin1String(NM_SSH_DEFAULT_REMOTE_USERNAME)); KAcceleratorManager::manage(this); if (d->setting && !d->setting->isNull()) { loadConfig(d->setting); } } SshSettingWidget::~SshSettingWidget() { delete d_ptr; } void SshSettingWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { Q_D(SshSettingWidget); Q_UNUSED(setting) const NMStringMap dataMap = d->setting->data(); // General const QString gateway = dataMap[QLatin1String(NM_SSH_KEY_REMOTE)]; if (!gateway.isEmpty()) { d->ui.le_gateway->setText(gateway); } // Network settings const QString remoteIp = dataMap[QLatin1String(NM_SSH_KEY_REMOTE_IP)]; if (!remoteIp.isEmpty()) { d->ui.le_remoteIp->setText(remoteIp); } const QString localIp = dataMap[QLatin1String(NM_SSH_KEY_LOCAL_IP)]; if (!localIp.isEmpty()) { d->ui.le_localIp->setText(localIp); } const QString netmask = dataMap[QLatin1String(NM_SSH_KEY_NETMASK)]; if (!netmask.isEmpty()) { d->ui.le_netmask->setText(netmask); } // IPv6 network settings const bool ipv6Enabled = dataMap[QLatin1String(NM_SSH_KEY_IP_6)] == QLatin1String("yes"); d->ui.chk_useIpv6->setChecked(ipv6Enabled); if (ipv6Enabled) { const QString remoteIpv6 = dataMap[QLatin1String(NM_SSH_KEY_REMOTE_IP_6)]; if (!remoteIpv6.isEmpty()) { d->ui.le_remoteIpv6->setText(remoteIpv6); } const QString localIpv6 = dataMap[QLatin1String(NM_SSH_KEY_LOCAL_IP_6)]; if (!localIpv6.isEmpty()) { d->ui.le_localIpv6->setText(localIpv6); } const QString netmaskIpv6 = dataMap[QLatin1String(NM_SSH_KEY_NETMASK_6)]; if (!netmaskIpv6.isEmpty()) { d->ui.le_netmaskIpv6->setText(netmaskIpv6); } } // Authentication const QString sshAuthType = dataMap[QLatin1String(NM_SSH_KEY_AUTH_TYPE)]; if (sshAuthType == QLatin1String(NM_SSH_AUTH_TYPE_SSH_AGENT)) { d->ui.cmb_authType->setCurrentIndex(0); } else if (sshAuthType == QLatin1String(NM_SSH_AUTH_TYPE_PASSWORD)) { d->ui.cmb_authType->setCurrentIndex(1); const NetworkManager::Setting::SecretFlags type = (NetworkManager::Setting::SecretFlags)dataMap[NM_SSH_KEY_PASSWORD"-flags"].toInt(); fillOnePasswordCombo(d->ui.le_password, type); } else if (sshAuthType == QLatin1String(NM_SSH_AUTH_TYPE_KEY)) { d->ui.cmb_authType->setCurrentIndex(2); d->ui.kurl_sshKeyFile->setUrl(QUrl::fromLocalFile(dataMap[QLatin1String(NM_SSH_KEY_KEY_FILE)])); } // Options below is belongs to "Advanced" dialog const QString customGatewayPort = dataMap[QLatin1String(NM_SSH_KEY_PORT)]; if (!customGatewayPort.isEmpty()) { d->advUi.chk_useCustomGatewayPort->setChecked(true); d->advUi.sb_useCustomGatewayPort->setValue(customGatewayPort.toInt()); } const QString customMtu = dataMap[QLatin1String(NM_SSH_KEY_TUNNEL_MTU)]; if (!customMtu.isEmpty()) { d->advUi.chk_useCustomTunnelMtu->setChecked(true); d->advUi.sb_useCustomTunnelMtu->setValue(customMtu.toInt()); } const QString extraSshOptions = dataMap[QLatin1String(NM_SSH_KEY_EXTRA_OPTS)]; if (!extraSshOptions.isEmpty()) { d->advUi.chk_extraSshOptions->setChecked(true); d->advUi.le_extraSshOptions->setText(extraSshOptions); } const QString remoteDeviceNumber = dataMap[QLatin1String(NM_SSH_KEY_REMOTE_DEV)]; if (!remoteDeviceNumber.isEmpty()) { d->advUi.chk_remoteDeviceNumber->setChecked(true); d->advUi.sb_remoteDeviceNumber->setValue(remoteDeviceNumber.toInt()); } const QString useTapDevice = dataMap[QLatin1String(NM_SSH_KEY_TAP_DEV)]; if (!useTapDevice.isEmpty()) { if (useTapDevice == QLatin1String("yes")) { d->advUi.chk_useTapDevice->setChecked(true); } } const QString remoteUsername = dataMap[QLatin1String(NM_SSH_KEY_REMOTE_USERNAME)]; if (!remoteUsername.isEmpty()) { d->advUi.chk_remoteUsername->setChecked(true); d->advUi.le_remoteUsername->setText(remoteUsername); } const QString doNotReplaceDefaultRoute = dataMap[QLatin1String(NM_SSH_KEY_NO_DEFAULT_ROUTE)]; if (!doNotReplaceDefaultRoute.isEmpty()) { if (doNotReplaceDefaultRoute == QLatin1String("yes")) { d->advUi.chk_doNotReplaceDefaultRoute->setChecked(true); } } loadSecrets(setting); } void SshSettingWidget::loadSecrets(const NetworkManager::Setting::Ptr &setting) { Q_D(SshSettingWidget); NetworkManager::VpnSetting::Ptr vpnSetting = setting.staticCast(); if (vpnSetting) { const NMStringMap secrets = vpnSetting->secrets(); const QString keyPassword = secrets.value(NM_SSH_KEY_PASSWORD); if (!keyPassword.isEmpty()) { d->ui.le_password->setText(keyPassword); } } } QVariantMap SshSettingWidget::setting() const { Q_D(const SshSettingWidget); NetworkManager::VpnSetting setting; setting.setServiceType(QLatin1String(NM_DBUS_SERVICE_SSH)); NMStringMap data; NMStringMap secretData; data.insert(QLatin1String(NM_SSH_KEY_REMOTE), d->ui.le_gateway->text()); if (!d->ui.le_remoteIp->text().isEmpty()) { data.insert(QLatin1String(NM_SSH_KEY_REMOTE_IP), d->ui.le_remoteIp->text()); } if (!d->ui.le_localIp->text().isEmpty()) { data.insert(QLatin1String(NM_SSH_KEY_LOCAL_IP), d->ui.le_localIp->text()); } if (!d->ui.le_netmask->text().isEmpty()) { data.insert(QLatin1String(NM_SSH_KEY_NETMASK), d->ui.le_netmask->text()); } if (d->ui.chk_useIpv6->isChecked()) { data.insert(QLatin1String(NM_SSH_KEY_IP_6), QLatin1String("yes")); if (!d->ui.le_remoteIpv6->text().isEmpty()) { data.insert(QLatin1String(NM_SSH_KEY_REMOTE_IP_6), d->ui.le_remoteIpv6->text()); } if (!d->ui.le_localIpv6->text().isEmpty()) { data.insert(QLatin1String(NM_SSH_KEY_LOCAL_IP_6), d->ui.le_localIpv6->text()); } if (!d->ui.le_netmaskIpv6->text().isEmpty()) { data.insert(QLatin1String(NM_SSH_KEY_NETMASK_6), d->ui.le_netmaskIpv6->text()); } } switch (d->ui.cmb_authType->currentIndex()) { case 0: data.insert(QLatin1String(NM_SSH_KEY_AUTH_TYPE), QLatin1String(NM_SSH_AUTH_TYPE_SSH_AGENT)); break; case 1: data.insert(QLatin1String(NM_SSH_KEY_AUTH_TYPE), QLatin1String(NM_SSH_AUTH_TYPE_PASSWORD)); if (!d->ui.le_password->text().isEmpty()) { secretData.insert(QLatin1String(NM_SSH_KEY_PASSWORD), d->ui.le_password->text()); } handleOnePasswordType(d->ui.le_password, NM_SSH_KEY_PASSWORD"-flags", data); break; case 2: data.insert(QLatin1String(NM_SSH_KEY_AUTH_TYPE), QLatin1String(NM_SSH_AUTH_TYPE_KEY)); if (!d->ui.kurl_sshKeyFile->url().isEmpty()) { data.insert(QLatin1String(NM_SSH_KEY_KEY_FILE), d->ui.kurl_sshKeyFile->url().toLocalFile()); } break; } if (d->advUi.chk_useCustomGatewayPort->isChecked()) { data.insert(QLatin1String(NM_SSH_KEY_PORT), QString::number(d->advUi.sb_useCustomGatewayPort->value())); } if (d->advUi.chk_useCustomTunnelMtu->isChecked()) { data.insert(QLatin1String(NM_SSH_KEY_TUNNEL_MTU), QString::number(d->advUi.sb_useCustomTunnelMtu->value())); } if (d->advUi.chk_extraSshOptions->isChecked()) { data.insert(QLatin1String(NM_SSH_KEY_EXTRA_OPTS), d->advUi.le_extraSshOptions->text()); } if (d->advUi.chk_remoteDeviceNumber->isChecked()) { data.insert(QLatin1String(NM_SSH_KEY_REMOTE_DEV), QString::number(d->advUi.sb_remoteDeviceNumber->value())); } if (d->advUi.chk_useTapDevice->isChecked()) { data.insert(QLatin1String(NM_SSH_KEY_TAP_DEV), QLatin1String("yes")); } if (d->advUi.chk_remoteUsername->isChecked()) { data.insert(QLatin1String(NM_SSH_KEY_REMOTE_USERNAME), d->advUi.le_remoteUsername->text()); } if (d->advUi.chk_doNotReplaceDefaultRoute->isChecked()) { data.insert(QLatin1String(NM_SSH_KEY_NO_DEFAULT_ROUTE), QLatin1String("yes")); } // save it all setting.setData(data); setting.setSecrets(secretData); return setting.toMap(); } void SshSettingWidget::authTypeChanged(int index) { Q_D(SshSettingWidget); if (index == 0) { d->ui.stackedWidget->setCurrentIndex(0); d->ui.passwordWidget->setVisible(false); } else if (index == 1) { d->ui.stackedWidget->setCurrentIndex(0); d->ui.passwordWidget->setVisible(true); } else { d->ui.stackedWidget->setCurrentIndex(1); } } void SshSettingWidget::doAdvancedDialog() { Q_D(SshSettingWidget); d->advancedDlg->show(); } void SshSettingWidget::passwordTypeChanged(int index) { Q_D(SshSettingWidget); d->ui.le_password->setEnabled(index == SettingWidget::EnumPasswordStorageType::Store); } void SshSettingWidget::fillOnePasswordCombo(PasswordField *passwordField, NetworkManager::Setting::SecretFlags type) { if (type.testFlag(NetworkManager::Setting::None)) { passwordField->setPasswordOption(PasswordField::StoreForAllUsers); } else if (type.testFlag(NetworkManager::Setting::AgentOwned)) { passwordField->setPasswordOption(PasswordField::StoreForUser); } else if (type.testFlag(NetworkManager::Setting::NotSaved)) { passwordField->setPasswordOption(PasswordField::AlwaysAsk); } else { passwordField->setPasswordOption(PasswordField::PasswordField::NotRequired); } } void SshSettingWidget::handleOnePasswordType(const PasswordField *passwordField, const QString &key, NMStringMap &data) const { const PasswordField::PasswordOption option = passwordField->passwordOption(); switch (option) { case PasswordField::StoreForAllUsers: data.insert(key, QString::number(NetworkManager::Setting::None)); break; case PasswordField::StoreForUser: data.insert(key, QString::number(NetworkManager::Setting::AgentOwned)); break; case PasswordField::AlwaysAsk: data.insert(key, QString::number(NetworkManager::Setting::NotSaved)); break; case PasswordField::NotRequired: data.insert(key, QString::number(NetworkManager::Setting::NotRequired)); break; } } bool SshSettingWidget::isValid() const { Q_D(const SshSettingWidget); return !d->ui.le_gateway->text().isEmpty() && !d->ui.le_localIp->text().isEmpty() && !d->ui.le_remoteIp->text().isEmpty() && !d->ui.le_netmask->text().isEmpty(); }