File indexing completed on 2024-04-21 16:20:26

0001 /*
0002     SPDX-FileCopyrightText: 2011 Ilia Kats <ilia-kats@gmx.net>
0003     SPDX-FileCopyrightText: 2013 Lukáš Tinkl <ltinkl@redhat.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006 */
0007 
0008 #include "openvpnauth.h"
0009 #include "passwordfield.h"
0010 
0011 #include <QCheckBox>
0012 #include <QFormLayout>
0013 #include <QLabel>
0014 #include <QString>
0015 
0016 #include <KLocalizedString>
0017 
0018 #include "nm-openvpn-service.h"
0019 #include "plasma_nm_openvpn.h"
0020 
0021 class OpenVpnAuthWidgetPrivate
0022 {
0023 public:
0024     NetworkManager::VpnSetting::Ptr setting;
0025     QFormLayout *layout;
0026 };
0027 
0028 OpenVpnAuthWidget::OpenVpnAuthWidget(const NetworkManager::VpnSetting::Ptr &setting, const QStringList &hints, QWidget *parent)
0029     : SettingWidget(setting, hints, parent)
0030     , d_ptr(new OpenVpnAuthWidgetPrivate)
0031 {
0032     Q_D(OpenVpnAuthWidget);
0033     d->setting = setting;
0034     d->layout = new QFormLayout(this);
0035     setLayout(d->layout);
0036 
0037     readSecrets();
0038 
0039     KAcceleratorManager::manage(this);
0040 }
0041 
0042 OpenVpnAuthWidget::~OpenVpnAuthWidget()
0043 {
0044     delete d_ptr;
0045 }
0046 
0047 void OpenVpnAuthWidget::readSecrets()
0048 {
0049     Q_D(OpenVpnAuthWidget);
0050 
0051     const NMStringMap dataMap = d->setting->data();
0052     const NMStringMap secrets = d->setting->secrets();
0053     const QString cType = dataMap[NM_OPENVPN_KEY_CONNECTION_TYPE];
0054     NetworkManager::Setting::SecretFlags certType = (NetworkManager::Setting::SecretFlags)dataMap.value(NM_OPENVPN_KEY_CERTPASS "-flags").toInt();
0055     NetworkManager::Setting::SecretFlags passType = (NetworkManager::Setting::SecretFlags)dataMap.value(NM_OPENVPN_KEY_PASSWORD "-flags").toInt();
0056     NetworkManager::Setting::SecretFlags proxyType = (NetworkManager::Setting::SecretFlags)dataMap.value(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD "-flags").toInt();
0057 
0058     // If hints are given, then always ask for what the hints require
0059     if (!m_hints.isEmpty()) {
0060         QString passwordType;
0061         QString prompt;
0062         for (const QString &hint : std::as_const(m_hints)) {
0063             const QString vpnMessage = QStringLiteral("x-vpn-message:");
0064             if (hint.startsWith(vpnMessage)) {
0065                 prompt = hint.right(hint.length() - vpnMessage.length());
0066             } else {
0067                 passwordType = hint;
0068             }
0069         }
0070 
0071         if (prompt.isEmpty()) {
0072             if (passwordType == QLatin1String(NM_OPENVPN_KEY_CERTPASS)) {
0073                 prompt = i18n("Key Password:");
0074             } else if (passwordType == QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD)) {
0075                 prompt = i18n("Proxy Password:");
0076             } else {
0077                 prompt = i18n("Password:");
0078             }
0079         } else if (prompt.endsWith(QLatin1Char('.'))) {
0080             prompt = prompt.replace(prompt.length() - 1, 1, QLatin1Char(':'));
0081         } else if (!prompt.endsWith(QLatin1Char(':'))) {
0082             prompt += QLatin1Char(':');
0083         }
0084 
0085         bool isOTP = false;
0086         QStringList possibleTokens = {i18n("OTP"), i18n("authenticator"), i18n("code"), i18n("token"), i18n("one-time password")};
0087         for (const QString &possibleToken : possibleTokens) {
0088             if (prompt.toLower().contains(possibleToken.toLower())) {
0089                 isOTP = true;
0090                 break;
0091             }
0092         }
0093 
0094         addPasswordField(prompt, QString(), passwordType, !isOTP);
0095     } else {
0096         if (cType == QLatin1String(NM_OPENVPN_CONTYPE_TLS) || cType == QLatin1String(NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
0097             // Normal user password
0098             if (cType == QLatin1String(NM_OPENVPN_CONTYPE_PASSWORD_TLS) && !passType.testFlag(NetworkManager::Setting::NotRequired)) {
0099                 addPasswordField(i18n("Password:"), secrets.value(QStringLiteral(NM_OPENVPN_KEY_PASSWORD)), QLatin1String(NM_OPENVPN_KEY_PASSWORD));
0100             }
0101             // Encrypted private key password
0102             if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_KEY)) && !certType.testFlag(NetworkManager::Setting::NotRequired)) {
0103                 addPasswordField(i18n("Key Password:"), secrets.value(QStringLiteral(NM_OPENVPN_KEY_CERTPASS)), QLatin1String(NM_OPENVPN_KEY_CERTPASS));
0104             }
0105         } else if (cType == QLatin1String(NM_OPENVPN_CONTYPE_PASSWORD)) {
0106             addPasswordField(i18n("Password:"), secrets.value(QStringLiteral(NM_OPENVPN_KEY_PASSWORD)), QLatin1String(NM_OPENVPN_KEY_PASSWORD));
0107         }
0108 
0109         if (dataMap.contains(NM_OPENVPN_KEY_PROXY_SERVER) && !proxyType.testFlag(NetworkManager::Setting::NotRequired)) {
0110             addPasswordField(i18n("Proxy Password:"),
0111                              secrets.value(QStringLiteral(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD)),
0112                              QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD));
0113         }
0114     }
0115 
0116     for (int i = 0; i < d->layout->rowCount(); i++) {
0117         auto le = qobject_cast<PasswordField *>(d->layout->itemAt(i, QFormLayout::FieldRole)->widget());
0118         if (le && le->text().isEmpty()) {
0119             le->setFocus(Qt::OtherFocusReason);
0120             break;
0121         }
0122     }
0123 }
0124 
0125 QVariantMap OpenVpnAuthWidget::setting() const
0126 {
0127     Q_D(const OpenVpnAuthWidget);
0128 
0129     NMStringMap secrets;
0130     QVariantMap secretData;
0131     for (int i = 0; i < d->layout->rowCount(); i++) {
0132         auto le = qobject_cast<PasswordField *>(d->layout->itemAt(i, QFormLayout::FieldRole)->widget());
0133         if (le && !le->text().isEmpty()) {
0134             const QString key = le->property("nm_secrets_key").toString();
0135             secrets.insert(key, le->text());
0136         }
0137     }
0138 
0139     secretData.insert("secrets", QVariant::fromValue<NMStringMap>(secrets));
0140     return secretData;
0141 }
0142 
0143 void OpenVpnAuthWidget::addPasswordField(const QString &labelText, const QString &password, const QString &secretKey, bool passwordMode)
0144 {
0145     Q_D(const OpenVpnAuthWidget);
0146 
0147     auto label = new QLabel(this);
0148     label->setText(labelText);
0149     auto lineEdit = new PasswordField(this);
0150     lineEdit->setPasswordModeEnabled(passwordMode);
0151     lineEdit->setProperty("nm_secrets_key", secretKey);
0152     lineEdit->setText(password);
0153     d->layout->addRow(label, lineEdit);
0154 }