File indexing completed on 2024-04-28 16:52:52

0001 /*
0002     SPDX-FileCopyrightText: 2015 Jan Grulich <jgrulich@redhat.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "sstpwidget.h"
0008 
0009 #include "ui_sstpadvanced.h"
0010 #include "ui_sstpwidget.h"
0011 
0012 #include <QDialog>
0013 #include <QDialogButtonBox>
0014 #include <QString>
0015 
0016 #include "nm-sstp-service.h"
0017 
0018 class SstpSettingWidgetPrivate
0019 {
0020 public:
0021     Ui_SstpWidget ui;
0022     Ui_SstpAdvanced advUi;
0023     NetworkManager::VpnSetting::Ptr setting;
0024     QDialog *advancedDlg = nullptr;
0025     QWidget *advancedWid = nullptr;
0026 };
0027 
0028 SstpSettingWidget::SstpSettingWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget *parent)
0029     : SettingWidget(setting, parent)
0030     , d_ptr(new SstpSettingWidgetPrivate)
0031 {
0032     Q_D(SstpSettingWidget);
0033     d->ui.setupUi(this);
0034 
0035     d->setting = setting;
0036 
0037     d->ui.le_password->setPasswordOptionsEnabled(true);
0038 
0039     connect(d->ui.btn_advancedOption, &QPushButton::clicked, this, &SstpSettingWidget::doAdvancedDialog);
0040 
0041     d->advancedDlg = new QDialog(this);
0042     d->advancedDlg->setModal(true);
0043     d->advancedWid = new QWidget(this);
0044     d->advUi.setupUi(d->advancedWid);
0045     auto layout = new QVBoxLayout(d->advancedDlg);
0046     layout->addWidget(d->advancedWid);
0047     d->advancedDlg->setLayout(layout);
0048     auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, d->advancedDlg);
0049     connect(buttons, &QDialogButtonBox::accepted, d->advancedDlg, &QDialog::accept);
0050     connect(buttons, &QDialogButtonBox::rejected, d->advancedDlg, &QDialog::reject);
0051 
0052     layout->addWidget(buttons);
0053 
0054     // Connect for setting check
0055     watchChangedSetting();
0056 
0057     // Connect for validity check
0058     connect(d->ui.le_gateway, &QLineEdit::textChanged, this, &SstpSettingWidget::slotWidgetChanged);
0059     connect(d->ui.le_username, &QLineEdit::textChanged, this, &SstpSettingWidget::slotWidgetChanged);
0060     connect(d->ui.le_password, &PasswordField::textChanged, this, &SstpSettingWidget::slotWidgetChanged);
0061 
0062     KAcceleratorManager::manage(this);
0063 
0064     if (d->setting && !d->setting->isNull()) {
0065         loadConfig(d->setting);
0066     }
0067 }
0068 
0069 SstpSettingWidget::~SstpSettingWidget()
0070 {
0071     delete d_ptr;
0072 }
0073 
0074 void SstpSettingWidget::loadConfig(const NetworkManager::Setting::Ptr &setting)
0075 {
0076     Q_D(SstpSettingWidget);
0077     Q_UNUSED(setting)
0078 
0079     const QString yesString = QLatin1String("yes");
0080     const NMStringMap dataMap = d->setting->data();
0081 
0082     // General
0083     const QString gateway = dataMap[QLatin1String(NM_SSTP_KEY_GATEWAY)];
0084     if (!gateway.isEmpty()) {
0085         d->ui.le_gateway->setText(gateway);
0086     }
0087 
0088     // Optional setting
0089     const QString username = dataMap[QLatin1String(NM_SSTP_KEY_USER)];
0090     if (!username.isEmpty()) {
0091         d->ui.le_username->setText(username);
0092     }
0093 
0094     // Authentication
0095     const NetworkManager::Setting::SecretFlags type = (NetworkManager::Setting::SecretFlags)dataMap[NM_SSTP_KEY_PASSWORD_FLAGS].toInt();
0096     fillOnePasswordCombo(d->ui.le_password, type);
0097 
0098     const QString ntDomain = dataMap[QLatin1String(NM_SSTP_KEY_DOMAIN)];
0099     if (!ntDomain.isEmpty()) {
0100         d->ui.le_ntDomain->setText(ntDomain);
0101     }
0102 
0103     const QString caCert = dataMap[QLatin1String(NM_SSTP_KEY_CA_CERT)];
0104     if (!caCert.isEmpty()) {
0105         d->ui.kurl_caCert->setUrl(QUrl::fromLocalFile(caCert));
0106     }
0107 
0108     const bool ignoreCertWarnings = (dataMap[QLatin1String(NM_SSTP_KEY_IGN_CERT_WARN)] == yesString);
0109     d->ui.chk_ignoreCertWarnings->setChecked(ignoreCertWarnings);
0110 
0111     // Advanced options - Point-to-Point
0112     bool refuse_pap = (dataMap[QLatin1String(NM_SSTP_KEY_REFUSE_PAP)] == yesString);
0113     bool refuse_chap = (dataMap[QLatin1String(NM_SSTP_KEY_REFUSE_CHAP)] == yesString);
0114     bool refuse_mschap = (dataMap[QLatin1String(NM_SSTP_KEY_REFUSE_MSCHAP)] == yesString);
0115     bool refuse_mschapv2 = (dataMap[QLatin1String(NM_SSTP_KEY_REFUSE_MSCHAPV2)] == yesString);
0116     bool refuse_eap = (dataMap[QLatin1String(NM_SSTP_KEY_REFUSE_EAP)] == yesString);
0117 
0118     QListWidgetItem *item = nullptr;
0119     item = d->advUi.listWidget->item(0); // PAP
0120     item->setCheckState(refuse_pap ? Qt::Unchecked : Qt::Checked);
0121     item = d->advUi.listWidget->item(1); // CHAP
0122     item->setCheckState(refuse_chap ? Qt::Unchecked : Qt::Checked);
0123     item = d->advUi.listWidget->item(2); // MSCHAP
0124     item->setCheckState(refuse_mschap ? Qt::Unchecked : Qt::Checked);
0125     item = d->advUi.listWidget->item(3); // MSCHAPv2
0126     item->setCheckState(refuse_mschapv2 ? Qt::Unchecked : Qt::Checked);
0127     item = d->advUi.listWidget->item(4); // EAP
0128     item->setCheckState(refuse_eap ? Qt::Unchecked : Qt::Checked);
0129 
0130     // Cryptography and compression
0131     const bool mppe = (dataMap[QLatin1String(NM_SSTP_KEY_REQUIRE_MPPE)] == yesString);
0132     const bool mppe40 = (dataMap[QLatin1String(NM_SSTP_KEY_REQUIRE_MPPE_40)] == yesString);
0133     const bool mppe128 = (dataMap[QLatin1String(NM_SSTP_KEY_REQUIRE_MPPE_128)] == yesString);
0134     const bool mppe_stateful = (dataMap[QLatin1String(NM_SSTP_KEY_MPPE_STATEFUL)] == yesString);
0135 
0136     if (mppe || mppe40 || mppe128) { // If MPPE is use
0137         d->advUi.gb_MPPE->setChecked(mppe || mppe40 || mppe128);
0138         if (mppe128) {
0139             d->advUi.cb_MPPECrypto->setCurrentIndex(1); // 128 bit
0140         } else if (mppe40) {
0141             d->advUi.cb_MPPECrypto->setCurrentIndex(2); // 40 bit
0142         } else {
0143             d->advUi.cb_MPPECrypto->setCurrentIndex(0); // Any
0144         }
0145         d->advUi.cb_statefulEncryption->setChecked(mppe_stateful);
0146     }
0147 
0148     const bool nobsd = (dataMap[QLatin1String(NM_SSTP_KEY_NOBSDCOMP)] == yesString);
0149     d->advUi.cb_BSD->setChecked(!nobsd);
0150 
0151     const bool nodeflate = (dataMap[QLatin1String(NM_SSTP_KEY_NODEFLATE)] == yesString);
0152     d->advUi.cb_deflate->setChecked(!nodeflate);
0153 
0154     const bool novjcomp = (dataMap[QLatin1String(NM_SSTP_KEY_NO_VJ_COMP)] == yesString);
0155     d->advUi.cb_TCPheaders->setChecked(!novjcomp);
0156 
0157     // Echo
0158     const int lcp_echo_interval = QString(dataMap[QLatin1String(NM_SSTP_KEY_LCP_ECHO_INTERVAL)]).toInt();
0159     d->advUi.cb_sendEcho->setChecked(lcp_echo_interval > 0);
0160 
0161     if (dataMap.contains(QLatin1String(NM_SSTP_KEY_UNIT_NUM))) {
0162         d->advUi.chk_useCustomUnitNumber->setChecked(true);
0163         d->advUi.sb_customUnitNumber->setValue(dataMap[QLatin1String(NM_SSTP_KEY_UNIT_NUM)].toInt());
0164     }
0165 
0166     // Advanced options - Proxy
0167     const QString address = dataMap[QLatin1String(NM_SSTP_KEY_PROXY_SERVER)];
0168     if (!address.isEmpty()) {
0169         d->advUi.le_address->setText(address);
0170     }
0171 
0172     const int port = dataMap[QLatin1String(NM_SSTP_KEY_PROXY_PORT)].toInt();
0173     if (port >= 0) {
0174         d->advUi.sb_port->setValue(port);
0175     }
0176 
0177     const QString proxyUsername = dataMap[QLatin1String(NM_SSTP_KEY_PROXY_USER)];
0178     if (!proxyUsername.isEmpty()) {
0179         d->advUi.le_username->setText(proxyUsername);
0180     }
0181 
0182     const QString proxyPassword = dataMap[QLatin1String(NM_SSTP_KEY_PROXY_PASSWORD)];
0183     if (!proxyPassword.isEmpty()) {
0184         d->advUi.le_password->setText(proxyPassword);
0185     }
0186 
0187     loadSecrets(setting);
0188 }
0189 
0190 void SstpSettingWidget::loadSecrets(const NetworkManager::Setting::Ptr &setting)
0191 {
0192     Q_D(SstpSettingWidget);
0193 
0194     NetworkManager::VpnSetting::Ptr vpnSetting = setting.staticCast<NetworkManager::VpnSetting>();
0195 
0196     if (vpnSetting) {
0197         const NMStringMap secrets = vpnSetting->secrets();
0198 
0199         const QString keyPassword = secrets.value(NM_SSTP_KEY_PASSWORD);
0200         if (!keyPassword.isEmpty()) {
0201             d->ui.le_password->setText(keyPassword);
0202         }
0203     }
0204 }
0205 
0206 QVariantMap SstpSettingWidget::setting() const
0207 {
0208     Q_D(const SstpSettingWidget);
0209 
0210     NetworkManager::VpnSetting setting;
0211     setting.setServiceType(QLatin1String(NM_DBUS_SERVICE_SSTP));
0212 
0213     const QString yesString = QLatin1String("yes");
0214 
0215     NMStringMap data;
0216     NMStringMap secretData;
0217 
0218     data.insert(QLatin1String(NM_SSTP_KEY_GATEWAY), d->ui.le_gateway->text());
0219 
0220     if (!d->ui.le_username->text().isEmpty()) {
0221         data.insert(QLatin1String(NM_SSTP_KEY_USER), d->ui.le_username->text());
0222     }
0223 
0224     if (!d->ui.le_password->text().isEmpty()) {
0225         secretData.insert(QLatin1String(NM_SSTP_KEY_PASSWORD), d->ui.le_password->text());
0226     }
0227     handleOnePasswordType(d->ui.le_password, NM_SSTP_KEY_PASSWORD_FLAGS, data);
0228 
0229     if (!d->ui.le_ntDomain->text().isEmpty()) {
0230         data.insert(QLatin1String(NM_SSTP_KEY_DOMAIN), d->ui.le_ntDomain->text());
0231     }
0232 
0233     if (!d->ui.kurl_caCert->url().isEmpty()) {
0234         data.insert(QLatin1String(NM_SSTP_KEY_CA_CERT), d->ui.kurl_caCert->url().toLocalFile());
0235     }
0236 
0237     if (d->ui.chk_ignoreCertWarnings->isChecked()) {
0238         data.insert(QLatin1String(NM_SSTP_KEY_IGN_CERT_WARN), yesString);
0239     }
0240 
0241     // Advanced configuration
0242     QListWidgetItem *item = nullptr;
0243     item = d->advUi.listWidget->item(0); // PAP
0244     if (item->checkState() == Qt::Unchecked) {
0245         data.insert(QLatin1String(NM_SSTP_KEY_REFUSE_PAP), yesString);
0246     }
0247     item = d->advUi.listWidget->item(1); // CHAP
0248     if (item->checkState() == Qt::Unchecked) {
0249         data.insert(QLatin1String(NM_SSTP_KEY_REFUSE_CHAP), yesString);
0250     }
0251     item = d->advUi.listWidget->item(2); // MSCHAP
0252     if (item->checkState() == Qt::Unchecked) {
0253         data.insert(QLatin1String(NM_SSTP_KEY_REFUSE_MSCHAP), yesString);
0254     }
0255     item = d->advUi.listWidget->item(3); // MSCHAPv2
0256     if (item->checkState() == Qt::Unchecked) {
0257         data.insert(QLatin1String(NM_SSTP_KEY_REFUSE_MSCHAPV2), yesString);
0258     }
0259     item = d->advUi.listWidget->item(4); // EAP
0260     if (item->checkState() == Qt::Unchecked) {
0261         data.insert(QLatin1String(NM_SSTP_KEY_REFUSE_EAP), yesString);
0262     }
0263 
0264     // Cryptography and compression
0265     if (d->advUi.gb_MPPE->isChecked()) {
0266         int index = d->advUi.cb_MPPECrypto->currentIndex();
0267 
0268         switch (index) {
0269         case 0:
0270             data.insert(QLatin1String(NM_SSTP_KEY_REQUIRE_MPPE), yesString);
0271             break;
0272         case 1:
0273             data.insert(QLatin1String(NM_SSTP_KEY_REQUIRE_MPPE_128), yesString);
0274             break;
0275         case 2:
0276             data.insert(QLatin1String(NM_SSTP_KEY_REQUIRE_MPPE_40), yesString);
0277             break;
0278         }
0279 
0280         if (d->advUi.cb_statefulEncryption->isChecked()) {
0281             data.insert(NM_SSTP_KEY_MPPE_STATEFUL, yesString);
0282         }
0283     }
0284 
0285     if (!d->advUi.cb_BSD->isChecked()) {
0286         data.insert(QLatin1String(NM_SSTP_KEY_NOBSDCOMP), yesString);
0287     }
0288 
0289     if (!d->advUi.cb_deflate->isChecked()) {
0290         data.insert(QLatin1String(NM_SSTP_KEY_NODEFLATE), yesString);
0291     }
0292 
0293     if (!d->advUi.cb_TCPheaders->isChecked()) {
0294         data.insert(QLatin1String(NM_SSTP_KEY_NO_VJ_COMP), yesString);
0295     }
0296 
0297     // Echo
0298     if (d->advUi.cb_sendEcho->isChecked()) {
0299         data.insert(QLatin1String(NM_SSTP_KEY_LCP_ECHO_FAILURE), "5");
0300         data.insert(QLatin1String(NM_SSTP_KEY_LCP_ECHO_INTERVAL), "30");
0301     }
0302 
0303     if (d->advUi.chk_useCustomUnitNumber->isChecked()) {
0304         data.insert(QLatin1String(NM_SSTP_KEY_UNIT_NUM), QString::number(d->advUi.sb_customUnitNumber->value()));
0305     }
0306 
0307     if (!d->advUi.le_address->text().isEmpty()) {
0308         data.insert(QLatin1String(NM_SSTP_KEY_PROXY_SERVER), d->advUi.le_address->text());
0309     }
0310 
0311     if (d->advUi.sb_port->value() >= 0) {
0312         data.insert(QLatin1String(NM_SSTP_KEY_PROXY_PORT), QString::number(d->advUi.sb_port->value()));
0313     }
0314 
0315     if (!d->advUi.le_username->text().isEmpty()) {
0316         data.insert(QLatin1String(NM_SSTP_KEY_PROXY_USER), d->advUi.le_username->text());
0317     }
0318 
0319     if (!d->advUi.le_password->text().isEmpty()) {
0320         data.insert(QLatin1String(NM_SSTP_KEY_PROXY_PASSWORD), d->advUi.le_password->text());
0321     }
0322     handleOnePasswordType(d->advUi.le_password, NM_SSTP_KEY_PROXY_PASSWORD_FLAGS, data);
0323 
0324     // save it all
0325     setting.setData(data);
0326     setting.setSecrets(secretData);
0327 
0328     return setting.toMap();
0329 }
0330 
0331 void SstpSettingWidget::doAdvancedDialog()
0332 {
0333     Q_D(SstpSettingWidget);
0334     d->advancedDlg->show();
0335 }
0336 
0337 void SstpSettingWidget::fillOnePasswordCombo(PasswordField *passwordField, NetworkManager::Setting::SecretFlags type)
0338 {
0339     if (type.testFlag(NetworkManager::Setting::None)) {
0340         passwordField->setPasswordOption(PasswordField::StoreForAllUsers);
0341     } else if (type.testFlag(NetworkManager::Setting::AgentOwned)) {
0342         passwordField->setPasswordOption(PasswordField::StoreForUser);
0343     } else if (type.testFlag(NetworkManager::Setting::NotSaved)) {
0344         passwordField->setPasswordOption(PasswordField::AlwaysAsk);
0345     } else {
0346         passwordField->setPasswordOption(PasswordField::PasswordField::NotRequired);
0347     }
0348 }
0349 
0350 void SstpSettingWidget::handleOnePasswordType(const PasswordField *passwordField, const QString &key, NMStringMap &data) const
0351 {
0352     const PasswordField::PasswordOption option = passwordField->passwordOption();
0353     switch (option) {
0354     case PasswordField::StoreForAllUsers:
0355         data.insert(key, QString::number(NetworkManager::Setting::None));
0356         break;
0357     case PasswordField::StoreForUser:
0358         data.insert(key, QString::number(NetworkManager::Setting::AgentOwned));
0359         break;
0360     case PasswordField::AlwaysAsk:
0361         data.insert(key, QString::number(NetworkManager::Setting::NotSaved));
0362         break;
0363     case PasswordField::NotRequired:
0364         data.insert(key, QString::number(NetworkManager::Setting::NotRequired));
0365         break;
0366     }
0367 }
0368 
0369 bool SstpSettingWidget::isValid() const
0370 {
0371     Q_D(const SstpSettingWidget);
0372 
0373     return !d->ui.le_gateway->text().isEmpty();
0374 }