File indexing completed on 2024-05-05 17:42:51

0001 /*
0002     SPDX-FileCopyrightText: 2013 Jan Grulich <jgrulich@redhat.com>
0003     SPDX-FileCopyrightText: 2020 Douglas Kosovic <doug@uq.edu.au>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 
0008 #include "l2tpwidget.h"
0009 #include "l2tpipsecwidget.h"
0010 #include "l2tppppwidget.h"
0011 #include "nm-l2tp-service.h"
0012 #include "ui_l2tp.h"
0013 
0014 #include <NetworkManagerQt/Setting>
0015 
0016 #include <QDBusMetaType>
0017 #include <QPointer>
0018 
0019 L2tpWidget::L2tpWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget *parent, Qt::WindowFlags f)
0020     : SettingWidget(setting, parent, f)
0021     , m_ui(new Ui::L2tpWidget)
0022     , m_setting(setting)
0023 {
0024     qDBusRegisterMetaType<NMStringMap>();
0025 
0026     m_ui->setupUi(this);
0027 
0028     m_ui->password->setPasswordOptionsEnabled(true);
0029     m_ui->userKeyPassword->setPasswordOptionsEnabled(true);
0030     m_ui->userKeyPassword->setPasswordNotRequiredEnabled(true);
0031 
0032     // use requesters' urlSelected signals to set other requester's startDirs to save clicking
0033     // around the filesystem, also if it is a .p12 file,  set the other URLs to that .p12 file.
0034     QList<const KUrlRequester *> requesters;
0035     requesters << m_ui->userCA << m_ui->userCert << m_ui->userKey;
0036     for (const KUrlRequester *requester : std::as_const(requesters)) {
0037         connect(requester, &KUrlRequester::urlSelected, this, &L2tpWidget::updateStartDirUrl);
0038     }
0039 
0040     if (L2tpIpsecWidget::hasIpsecDaemon()) {
0041         connect(m_ui->btnIPSecSettings, &QPushButton::clicked, this, &L2tpWidget::showIpsec);
0042     } else {
0043         m_ui->btnIPSecSettings->setDisabled(true);
0044     }
0045     connect(m_ui->btnPPPSettings, &QPushButton::clicked, this, &L2tpWidget::showPpp);
0046 
0047     // Connect for setting check
0048     watchChangedSetting();
0049 
0050     // Connect for validity check
0051     connect(m_ui->gateway, &QLineEdit::textChanged, this, &L2tpWidget::slotWidgetChanged);
0052 
0053     KAcceleratorManager::manage(this);
0054 
0055     if (setting && !setting->isNull()) {
0056         loadConfig(setting);
0057     }
0058 }
0059 
0060 L2tpWidget::~L2tpWidget()
0061 {
0062     m_tmpIpsecSetting.clear();
0063     m_tmpPppSetting.clear();
0064     delete m_ui;
0065 }
0066 
0067 void L2tpWidget::loadConfig(const NetworkManager::Setting::Ptr &setting)
0068 {
0069     Q_UNUSED(setting);
0070 
0071     const NMStringMap dataMap = m_setting->data();
0072 
0073     m_ui->gateway->setText(dataMap[NM_L2TP_KEY_GATEWAY]);
0074 
0075     if (dataMap[NM_L2TP_KEY_USER_AUTH_TYPE].isEmpty() || dataMap[NM_L2TP_KEY_USER_AUTH_TYPE] == QLatin1String(NM_L2TP_AUTHTYPE_PASSWORD)) {
0076         m_ui->cmbAuthType->setCurrentIndex(AuthType::Password);
0077         m_ui->stackedWidget->setCurrentIndex(AuthType::Password);
0078         m_ui->username->setText(dataMap[NM_L2TP_KEY_USER]);
0079 
0080         const NetworkManager::Setting::SecretFlags userPassType =
0081             static_cast<NetworkManager::Setting::SecretFlags>(dataMap[NM_L2TP_KEY_PASSWORD "-flags"].toInt());
0082         if (userPassType.testFlag(NetworkManager::Setting::None)) {
0083             m_ui->password->setPasswordOption(PasswordField::StoreForAllUsers);
0084         } else if (userPassType.testFlag(NetworkManager::Setting::AgentOwned)) {
0085             m_ui->password->setPasswordOption(PasswordField::StoreForUser);
0086         } else {
0087             m_ui->password->setPasswordOption(PasswordField::AlwaysAsk);
0088         }
0089 
0090         m_ui->domain->setText(dataMap[NM_L2TP_KEY_DOMAIN]);
0091 
0092     } else { // NM_L2TP_AUTHTYPE_TLS
0093         m_ui->cmbAuthType->setCurrentIndex(AuthType::TLS);
0094         m_ui->stackedWidget->setCurrentIndex(AuthType::TLS);
0095 
0096         m_ui->userCA->setUrl(QUrl::fromLocalFile(dataMap[NM_L2TP_KEY_USER_CA]));
0097         m_ui->userCert->setUrl(QUrl::fromLocalFile(dataMap[NM_L2TP_KEY_USER_CERT]));
0098         m_ui->userKey->setUrl(QUrl::fromLocalFile(dataMap[NM_L2TP_KEY_USER_KEY]));
0099 
0100         const NetworkManager::Setting::SecretFlags userKeyPassType =
0101             static_cast<NetworkManager::Setting::SecretFlags>(dataMap[NM_L2TP_KEY_USER_CERTPASS "-flags"].toInt());
0102         if (userKeyPassType.testFlag(NetworkManager::Setting::None)) {
0103             m_ui->userKeyPassword->setPasswordOption(PasswordField::StoreForAllUsers);
0104         } else if (userKeyPassType.testFlag(NetworkManager::Setting::AgentOwned)) {
0105             m_ui->userKeyPassword->setPasswordOption(PasswordField::StoreForUser);
0106         } else if (userKeyPassType.testFlag(NetworkManager::Setting::NotSaved)) {
0107             m_ui->userKeyPassword->setPasswordOption(PasswordField::AlwaysAsk);
0108         } else if (userKeyPassType.testFlag(NetworkManager::Setting::NotRequired)) {
0109             m_ui->userKeyPassword->setPasswordOption(PasswordField::NotRequired);
0110         }
0111     }
0112 
0113     loadSecrets(setting);
0114 }
0115 
0116 void L2tpWidget::loadSecrets(const NetworkManager::Setting::Ptr &setting)
0117 {
0118     NetworkManager::VpnSetting::Ptr vpnSetting = setting.staticCast<NetworkManager::VpnSetting>();
0119 
0120     if (vpnSetting) {
0121         const QString authType = m_setting->data().value(NM_L2TP_KEY_USER_AUTH_TYPE);
0122         const NMStringMap secrets = vpnSetting->secrets();
0123 
0124         if (authType == QLatin1String(NM_L2TP_AUTHTYPE_TLS)) {
0125             m_ui->userKeyPassword->setText(secrets.value(NM_L2TP_KEY_USER_CERTPASS));
0126         } else { // NM_L2TP_AUTHTYPE_PASSWORD
0127             m_ui->password->setText(secrets.value(NM_L2TP_KEY_PASSWORD));
0128         }
0129     }
0130 }
0131 
0132 QVariantMap L2tpWidget::setting() const
0133 {
0134     NetworkManager::VpnSetting setting;
0135     setting.setServiceType(QLatin1String(NM_DBUS_SERVICE_L2TP));
0136     NMStringMap data;
0137     NMStringMap secrets;
0138 
0139     if (!m_tmpIpsecSetting.isNull()) {
0140         data = m_tmpIpsecSetting->data();
0141         secrets = m_tmpIpsecSetting->secrets();
0142     } else {
0143         // retrieve the settings if the dialog has not been opened
0144         QScopedPointer<L2tpIpsecWidget> ipsec(new L2tpIpsecWidget(m_setting, nullptr));
0145         data = ipsec->setting();
0146         secrets = ipsec->secrets();
0147     }
0148 
0149     if (!m_tmpPppSetting.isNull()) {
0150         data.insert(m_tmpPppSetting->data());
0151     } else {
0152         const bool need_peer_eap = m_ui->cmbAuthType->currentIndex() != AuthType::Password;
0153 
0154         // retrieve the settings if the dialog has not been opened
0155         QScopedPointer<L2tpPPPWidget> ppp(new L2tpPPPWidget(m_setting, nullptr, need_peer_eap));
0156         data.insert(ppp->setting());
0157     }
0158 
0159     if (!m_ui->gateway->text().isEmpty()) {
0160         data.insert(NM_L2TP_KEY_GATEWAY, m_ui->gateway->text());
0161     }
0162 
0163     if (m_ui->cmbAuthType->currentIndex() == AuthType::Password) {
0164         if (!m_ui->username->text().isEmpty()) {
0165             data.insert(NM_L2TP_KEY_USER, m_ui->username->text());
0166         }
0167 
0168         if (!m_ui->password->text().isEmpty()) {
0169             secrets.insert(NM_L2TP_KEY_PASSWORD, m_ui->password->text());
0170         } else {
0171             secrets.remove(NM_L2TP_KEY_PASSWORD);
0172         }
0173 
0174         switch (m_ui->password->passwordOption()) {
0175         case PasswordField::StoreForAllUsers:
0176             data.insert(NM_L2TP_KEY_PASSWORD "-flags", QString::number(NetworkManager::Setting::None));
0177             break;
0178         case PasswordField::StoreForUser:
0179             data.insert(NM_L2TP_KEY_PASSWORD "-flags", QString::number(NetworkManager::Setting::AgentOwned));
0180             break;
0181         default:
0182             data.insert(NM_L2TP_KEY_PASSWORD "-flags", QString::number(NetworkManager::Setting::NotSaved));
0183         };
0184 
0185         if (!m_ui->domain->text().isEmpty()) {
0186             data.insert(NM_L2TP_KEY_DOMAIN, m_ui->domain->text());
0187         }
0188 
0189     } else { // EnumAuthType::TLS
0190 
0191         data.insert(NM_L2TP_KEY_USER_AUTH_TYPE, NM_L2TP_AUTHTYPE_TLS);
0192 
0193         data.insert(NM_L2TP_KEY_USER_CA, m_ui->userCA->url().toLocalFile());
0194         data.insert(NM_L2TP_KEY_USER_CERT, m_ui->userCert->url().toLocalFile());
0195         data.insert(NM_L2TP_KEY_USER_KEY, m_ui->userKey->url().toLocalFile());
0196 
0197         // key password
0198         if (!m_ui->userKeyPassword->text().isEmpty()) {
0199             secrets.insert(NM_L2TP_KEY_USER_CERTPASS, m_ui->userKeyPassword->text());
0200         } else {
0201             secrets.remove(NM_L2TP_KEY_USER_CERTPASS);
0202         }
0203 
0204         switch (m_ui->userKeyPassword->passwordOption()) {
0205         case PasswordField::StoreForAllUsers:
0206             data.insert(NM_L2TP_KEY_USER_CERTPASS "-flags", QString::number(NetworkManager::Setting::None));
0207             break;
0208         case PasswordField::StoreForUser:
0209             data.insert(NM_L2TP_KEY_USER_CERTPASS "-flags", QString::number(NetworkManager::Setting::AgentOwned));
0210             break;
0211         case PasswordField::AlwaysAsk:
0212             data.insert(NM_L2TP_KEY_USER_CERTPASS "-flags", QString::number(NetworkManager::Setting::NotSaved));
0213             break;
0214         case PasswordField::NotRequired:
0215             data.insert(NM_L2TP_KEY_USER_CERTPASS "-flags", QString::number(NetworkManager::Setting::NotRequired));
0216             break;
0217         };
0218     }
0219 
0220     setting.setData(data);
0221     setting.setSecrets(secrets);
0222     return setting.toMap();
0223 }
0224 
0225 void L2tpWidget::updateStartDirUrl(const QUrl &url)
0226 {
0227     QList<KUrlRequester *> requesters;
0228     requesters << m_ui->userCA << m_ui->userCert << m_ui->userKey;
0229     bool isP12 = url.toString().endsWith(QLatin1String(".p12"));
0230 
0231     for (KUrlRequester *requester : std::as_const(requesters)) {
0232         requester->setStartDir(url.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash));
0233         if (isP12) {
0234             requester->setUrl(url);
0235         }
0236     }
0237 }
0238 
0239 void L2tpWidget::showIpsec()
0240 {
0241     QPointer<L2tpIpsecWidget> ipsec;
0242     if (m_tmpIpsecSetting.isNull()) {
0243         ipsec = new L2tpIpsecWidget(m_setting, this);
0244     } else {
0245         ipsec = new L2tpIpsecWidget(m_tmpIpsecSetting, this);
0246     }
0247     ipsec->setAttribute(Qt::WA_DeleteOnClose);
0248     connect(ipsec.data(), &L2tpIpsecWidget::accepted, [ipsec, this]() {
0249         NMStringMap ipsecData = ipsec->setting();
0250         if (!ipsecData.isEmpty()) {
0251             if (m_tmpIpsecSetting.isNull()) {
0252                 m_tmpIpsecSetting = NetworkManager::VpnSetting::Ptr(new NetworkManager::VpnSetting);
0253             }
0254             m_tmpIpsecSetting->setData(ipsecData);
0255         }
0256     });
0257     ipsec->setModal(true);
0258     ipsec->show();
0259 }
0260 
0261 void L2tpWidget::showPpp()
0262 {
0263     QPointer<L2tpPPPWidget> ipsec;
0264     bool need_peer_eap = m_ui->cmbAuthType->currentIndex() != AuthType::Password;
0265     if (m_tmpPppSetting.isNull()) {
0266         ipsec = new L2tpPPPWidget(m_setting, this, need_peer_eap);
0267     } else {
0268         ipsec = new L2tpPPPWidget(m_tmpPppSetting, this, need_peer_eap);
0269     }
0270     ipsec->setAttribute(Qt::WA_DeleteOnClose);
0271     connect(ipsec.data(), &L2tpPPPWidget::accepted, [ipsec, this]() {
0272         NMStringMap ipsecData = ipsec->setting();
0273         if (!ipsecData.isEmpty()) {
0274             if (m_tmpPppSetting.isNull()) {
0275                 m_tmpPppSetting = NetworkManager::VpnSetting::Ptr(new NetworkManager::VpnSetting);
0276             }
0277             m_tmpPppSetting->setData(ipsecData);
0278         }
0279     });
0280     ipsec->setModal(true);
0281     ipsec->show();
0282 }
0283 
0284 bool L2tpWidget::isValid() const
0285 {
0286     return !m_ui->gateway->text().isEmpty();
0287 }