File indexing completed on 2024-04-28 05:33:53

0001 /*
0002     SPDX-FileCopyrightText: 2013 Lukas Tinkl <ltinkl@redhat.com>
0003     SPDX-FileCopyrightText: 2013 Daniel Nicoletti <dantti12@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 
0008 #include "passworddialog.h"
0009 #include "plasma_nm_kded.h"
0010 #include "ui_passworddialog.h"
0011 #include "uiutils.h"
0012 
0013 #include <vpnuiplugin.h>
0014 
0015 #include <NetworkManagerQt/Utils>
0016 #include <NetworkManagerQt/VpnSetting>
0017 #include <NetworkManagerQt/WirelessSetting>
0018 
0019 #include <KLocalizedString>
0020 
0021 #include <QIcon>
0022 #include <QPushButton>
0023 
0024 using namespace NetworkManager;
0025 
0026 PasswordDialog::PasswordDialog(const NetworkManager::ConnectionSettings::Ptr &connectionSettings,
0027                                SecretAgent::GetSecretsFlags flags,
0028                                const QString &setting_name,
0029                                const QStringList &hints,
0030                                QWidget *parent)
0031     : QDialog(parent)
0032     , m_settingName(setting_name)
0033     , m_connectionSettings(connectionSettings)
0034     , m_error(SecretAgent::NoSecrets)
0035     , m_flags(flags)
0036     , m_hints(hints)
0037 {
0038     setWindowIcon(QIcon::fromTheme(QStringLiteral("dialog-password")));
0039 
0040     initializeUi();
0041 }
0042 
0043 PasswordDialog::~PasswordDialog()
0044 {
0045     delete m_ui;
0046 }
0047 
0048 void PasswordDialog::initializeUi()
0049 {
0050     m_ui = new Ui::PasswordDialog;
0051     m_ui->setupUi(this);
0052     // TODO fix this for high DPI
0053     m_ui->labelIcon->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-password")).pixmap(64));
0054     m_ui->labelHeadline->setText(i18n("Authenticate %1", m_connectionSettings->id()));
0055 
0056     connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &PasswordDialog::accept);
0057     connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &PasswordDialog::reject);
0058     connect(m_ui->password, &PasswordField::textChanged, [this](const QString &text) {
0059         if (m_connectionSettings->connectionType() == NetworkManager::ConnectionSettings::Wireless) {
0060             NetworkManager::WirelessSecuritySetting::Ptr wirelessSecuritySetting =
0061                 m_connectionSettings->setting(NetworkManager::Setting::WirelessSecurity).staticCast<NetworkManager::WirelessSecuritySetting>();
0062             bool valid = true;
0063 
0064             if (wirelessSecuritySetting) {
0065                 switch (wirelessSecuritySetting->keyMgmt()) {
0066                 case NetworkManager::WirelessSecuritySetting::WpaPsk:
0067                     valid = wpaPskIsValid(text);
0068                     break;
0069                 case NetworkManager::WirelessSecuritySetting::Wep:
0070                     valid = wepKeyIsValid(text, wirelessSecuritySetting->wepKeyType());
0071                     break;
0072                 default:
0073                     break;
0074                 }
0075             }
0076 
0077             // disable button if key is not valid
0078             m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDisabled(!valid);
0079         }
0080     });
0081 
0082     if (m_connectionSettings->connectionType() != NetworkManager::ConnectionSettings::Vpn) {
0083         NetworkManager::Setting::Ptr setting = m_connectionSettings->setting(m_settingName);
0084         m_neededSecrets = setting->needSecrets(m_flags & SecretAgent::RequestNew);
0085 
0086         if (m_neededSecrets.isEmpty()) {
0087             qCWarning(PLASMA_NM_KDED_LOG) << "list of secrets is empty!!!";
0088             m_hasError = true;
0089             m_error = SecretAgent::InternalError;
0090             m_errorMessage = i18nc("@info:status 'secrets' means the authentication needed for a VPN", "No secrets were requested");
0091             return;
0092         }
0093 
0094         WirelessSetting::Ptr wifi = m_connectionSettings->setting(Setting::Wireless).dynamicCast<WirelessSetting>();
0095         Setting::SettingType connectionType = setting->type();
0096         if (wifi && (connectionType == Setting::WirelessSecurity || connectionType == Setting::Security8021x)) {
0097             const QString ssid = QString::fromUtf8(wifi->ssid());
0098             if (m_flags & NetworkManager::SecretAgent::RequestNew) {
0099                 m_ui->labelText->setText(i18n("Incorrect password for the wireless network \"%1\". Please try again.", ssid));
0100             } else {
0101                 m_ui->labelText->setText(i18n("Enter the password for the wireless network \"%1\":", ssid));
0102             }
0103         } else {
0104             if (m_flags & NetworkManager::SecretAgent::RequestNew) {
0105                 m_ui->labelText->setText(i18n("Incorrect password for the connection \"%1\". Please try again.", m_connectionSettings->id()));
0106             } else {
0107                 m_ui->labelText->setText(i18n("Enter the password for the connection \"%1\":", m_connectionSettings->id()));
0108             }
0109         }
0110 
0111         QString connectionLabel;
0112         UiUtils::iconAndTitleForConnectionSettingsType(m_connectionSettings->connectionType(), connectionLabel);
0113         setFocusProxy(m_ui->password);
0114         setWindowTitle(i18n("%1 password dialog", connectionLabel));
0115     } else {
0116         NetworkManager::VpnSetting::Ptr vpnSetting = m_connectionSettings->setting(Setting::Vpn).dynamicCast<VpnSetting>();
0117         if (!vpnSetting) {
0118             qCWarning(PLASMA_NM_KDED_LOG) << "Missing VPN setting!";
0119             m_hasError = true;
0120             m_error = SecretAgent::InternalError;
0121             m_errorMessage = i18nc("@info:status", "VPN settings are missing");
0122         } else {
0123             const QString serviceType = vpnSetting->serviceType();
0124             const auto result = VpnUiPlugin::loadPluginForType(this, serviceType);
0125 
0126             if (result) {
0127                 VpnUiPlugin *vpnUiPlugin = result.plugin;
0128                 const QString shortName = serviceType.section('.', -1);
0129                 NMStringMap data = vpnSetting->data();
0130                 m_vpnWidget = vpnUiPlugin->askUser(vpnSetting, m_hints, this);
0131                 auto layout = new QVBoxLayout();
0132                 layout->addWidget(m_vpnWidget);
0133                 m_ui->vpnWidget->setLayout(layout);
0134                 m_ui->labelText->setText(i18n("Provide the secrets for the VPN connection \"%1\":", m_connectionSettings->id()));
0135                 setWindowTitle(i18n("VPN secrets (%1) dialog", shortName));
0136 
0137                 // Hide generic password field and OK button in case of openconnect dialog
0138                 m_ui->labelPass->setVisible(false);
0139                 m_ui->password->setVisible(false);
0140                 if (shortName == QLatin1String("openconnect")) {
0141                     QAbstractButton *button = m_ui->buttonBox->button(QDialogButtonBox::Ok);
0142                     m_ui->buttonBox->removeButton(button);
0143                 }
0144 
0145                 setFocusProxy(m_vpnWidget);
0146                 m_vpnWidget->setFocus(Qt::OtherFocusReason);
0147             } else {
0148                 qCWarning(PLASMA_NM_KDED_LOG) << "Could not load VPN UI plugin" << result.errorText;
0149                 m_hasError = true;
0150                 m_error = SecretAgent::InternalError;
0151                 m_errorMessage = result.errorString;
0152             }
0153         }
0154     }
0155 
0156     // Workaround to force m_ui->password to get focus.
0157     focusNextChild();
0158 }
0159 
0160 bool PasswordDialog::hasError() const
0161 {
0162     return m_hasError;
0163 }
0164 
0165 SecretAgent::Error PasswordDialog::error() const
0166 {
0167     return m_error;
0168 }
0169 
0170 QString PasswordDialog::errorMessage() const
0171 {
0172     return m_errorMessage;
0173 }
0174 
0175 NMVariantMapMap PasswordDialog::secrets() const
0176 {
0177     NMVariantMapMap ret = m_connectionSettings->toMap();
0178     QVariantMap result;
0179     if (m_vpnWidget) {
0180         result = m_vpnWidget->setting();
0181     } else if (!m_ui->password->text().isEmpty() && !m_neededSecrets.isEmpty()) {
0182         result.insert(m_neededSecrets.first(), m_ui->password->text());
0183     }
0184 
0185     ret.insert(m_settingName, result);
0186 
0187     return ret;
0188 }
0189 
0190 #include "moc_passworddialog.cpp"