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 "sshwidget.h" 0008 0009 #include "ui_sshadvanced.h" 0010 #include "ui_sshwidget.h" 0011 0012 #include "simpleipv4addressvalidator.h" 0013 #include "simpleipv6addressvalidator.h" 0014 0015 #include <QDialog> 0016 #include <QDialogButtonBox> 0017 #include <QString> 0018 0019 #include "nm-ssh-service.h" 0020 0021 class SshSettingWidgetPrivate 0022 { 0023 public: 0024 Ui_SshWidget ui; 0025 Ui_SshAdvanced advUi; 0026 NetworkManager::VpnSetting::Ptr setting; 0027 QDialog *advancedDlg = nullptr; 0028 QWidget *advancedWid = nullptr; 0029 }; 0030 0031 SshSettingWidget::SshSettingWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget *parent) 0032 : SettingWidget(setting, parent) 0033 , d_ptr(new SshSettingWidgetPrivate) 0034 { 0035 Q_D(SshSettingWidget); 0036 d->ui.setupUi(this); 0037 0038 d->setting = setting; 0039 0040 d->ui.le_password->setPasswordOptionsEnabled(true); 0041 0042 connect(d->ui.cmb_authType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SshSettingWidget::authTypeChanged); 0043 connect(d->ui.btn_advancedOption, &QPushButton::clicked, this, &SshSettingWidget::doAdvancedDialog); 0044 0045 d->advancedDlg = new QDialog(this); 0046 d->advancedDlg->setModal(true); 0047 d->advancedWid = new QWidget(this); 0048 d->advUi.setupUi(d->advancedWid); 0049 auto layout = new QVBoxLayout(d->advancedDlg); 0050 layout->addWidget(d->advancedWid); 0051 d->advancedDlg->setLayout(layout); 0052 auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, d->advancedDlg); 0053 connect(buttons, &QDialogButtonBox::accepted, d->advancedDlg, &QDialog::accept); 0054 connect(buttons, &QDialogButtonBox::rejected, d->advancedDlg, &QDialog::reject); 0055 0056 layout->addWidget(buttons); 0057 0058 // Connect for setting check 0059 watchChangedSetting(); 0060 0061 // Connect for validity check 0062 connect(d->ui.le_gateway, &QLineEdit::textChanged, this, &SshSettingWidget::slotWidgetChanged); 0063 connect(d->ui.le_localIp, &QLineEdit::textChanged, this, &SshSettingWidget::slotWidgetChanged); 0064 connect(d->ui.le_netmask, &QLineEdit::textChanged, this, &SshSettingWidget::slotWidgetChanged); 0065 connect(d->ui.le_remoteIp, &QLineEdit::textChanged, this, &SshSettingWidget::slotWidgetChanged); 0066 0067 auto ipv4Validator = new SimpleIpV4AddressValidator(SimpleIpV4AddressValidator::Base, this); 0068 d->ui.le_localIp->setValidator(ipv4Validator); 0069 d->ui.le_remoteIp->setValidator(ipv4Validator); 0070 d->ui.le_netmask->setValidator(ipv4Validator); 0071 0072 auto ipv6Validator = new SimpleIpV6AddressValidator(SimpleIpV6AddressValidator::Base, this); 0073 d->ui.le_localIpv6->setValidator(ipv6Validator); 0074 d->ui.le_remoteIpv6->setValidator(ipv6Validator); 0075 0076 d->ui.passwordWidget->setVisible(false); 0077 d->advUi.sb_useCustomGatewayPort->setValue(NM_SSH_DEFAULT_PORT); 0078 d->advUi.sb_useCustomTunnelMtu->setValue(NM_SSH_DEFAULT_MTU); 0079 d->advUi.le_extraSshOptions->setText(QLatin1String(NM_SSH_DEFAULT_EXTRA_OPTS)); 0080 d->advUi.sb_remoteDeviceNumber->setValue(NM_SSH_DEFAULT_REMOTE_DEV); 0081 d->advUi.le_remoteUsername->setText(QLatin1String(NM_SSH_DEFAULT_REMOTE_USERNAME)); 0082 0083 KAcceleratorManager::manage(this); 0084 0085 if (d->setting && !d->setting->isNull()) { 0086 loadConfig(d->setting); 0087 } 0088 } 0089 0090 SshSettingWidget::~SshSettingWidget() 0091 { 0092 delete d_ptr; 0093 } 0094 0095 void SshSettingWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) 0096 { 0097 Q_D(SshSettingWidget); 0098 Q_UNUSED(setting) 0099 0100 const NMStringMap dataMap = d->setting->data(); 0101 0102 // General 0103 const QString gateway = dataMap[QLatin1String(NM_SSH_KEY_REMOTE)]; 0104 if (!gateway.isEmpty()) { 0105 d->ui.le_gateway->setText(gateway); 0106 } 0107 0108 // Network settings 0109 const QString remoteIp = dataMap[QLatin1String(NM_SSH_KEY_REMOTE_IP)]; 0110 if (!remoteIp.isEmpty()) { 0111 d->ui.le_remoteIp->setText(remoteIp); 0112 } 0113 0114 const QString localIp = dataMap[QLatin1String(NM_SSH_KEY_LOCAL_IP)]; 0115 if (!localIp.isEmpty()) { 0116 d->ui.le_localIp->setText(localIp); 0117 } 0118 0119 const QString netmask = dataMap[QLatin1String(NM_SSH_KEY_NETMASK)]; 0120 if (!netmask.isEmpty()) { 0121 d->ui.le_netmask->setText(netmask); 0122 } 0123 0124 // IPv6 network settings 0125 const bool ipv6Enabled = dataMap[QLatin1String(NM_SSH_KEY_IP_6)] == QLatin1String("yes"); 0126 d->ui.chk_useIpv6->setChecked(ipv6Enabled); 0127 0128 if (ipv6Enabled) { 0129 const QString remoteIpv6 = dataMap[QLatin1String(NM_SSH_KEY_REMOTE_IP_6)]; 0130 if (!remoteIpv6.isEmpty()) { 0131 d->ui.le_remoteIpv6->setText(remoteIpv6); 0132 } 0133 0134 const QString localIpv6 = dataMap[QLatin1String(NM_SSH_KEY_LOCAL_IP_6)]; 0135 if (!localIpv6.isEmpty()) { 0136 d->ui.le_localIpv6->setText(localIpv6); 0137 } 0138 0139 const QString netmaskIpv6 = dataMap[QLatin1String(NM_SSH_KEY_NETMASK_6)]; 0140 if (!netmaskIpv6.isEmpty()) { 0141 d->ui.le_netmaskIpv6->setText(netmaskIpv6); 0142 } 0143 } 0144 0145 // Authentication 0146 const QString sshAuthType = dataMap[QLatin1String(NM_SSH_KEY_AUTH_TYPE)]; 0147 if (sshAuthType == QLatin1String(NM_SSH_AUTH_TYPE_SSH_AGENT)) { 0148 d->ui.cmb_authType->setCurrentIndex(0); 0149 } else if (sshAuthType == QLatin1String(NM_SSH_AUTH_TYPE_PASSWORD)) { 0150 d->ui.cmb_authType->setCurrentIndex(1); 0151 const NetworkManager::Setting::SecretFlags type = (NetworkManager::Setting::SecretFlags)dataMap[NM_SSH_KEY_PASSWORD "-flags"].toInt(); 0152 fillOnePasswordCombo(d->ui.le_password, type); 0153 } else if (sshAuthType == QLatin1String(NM_SSH_AUTH_TYPE_KEY)) { 0154 d->ui.cmb_authType->setCurrentIndex(2); 0155 d->ui.kurl_sshKeyFile->setUrl(QUrl::fromLocalFile(dataMap[QLatin1String(NM_SSH_KEY_KEY_FILE)])); 0156 } 0157 0158 // Options below is belongs to "Advanced" dialog 0159 const QString customGatewayPort = dataMap[QLatin1String(NM_SSH_KEY_PORT)]; 0160 if (!customGatewayPort.isEmpty()) { 0161 d->advUi.chk_useCustomGatewayPort->setChecked(true); 0162 d->advUi.sb_useCustomGatewayPort->setValue(customGatewayPort.toInt()); 0163 } 0164 0165 const QString customMtu = dataMap[QLatin1String(NM_SSH_KEY_TUNNEL_MTU)]; 0166 if (!customMtu.isEmpty()) { 0167 d->advUi.chk_useCustomTunnelMtu->setChecked(true); 0168 d->advUi.sb_useCustomTunnelMtu->setValue(customMtu.toInt()); 0169 } 0170 0171 const QString extraSshOptions = dataMap[QLatin1String(NM_SSH_KEY_EXTRA_OPTS)]; 0172 if (!extraSshOptions.isEmpty()) { 0173 d->advUi.chk_extraSshOptions->setChecked(true); 0174 d->advUi.le_extraSshOptions->setText(extraSshOptions); 0175 } 0176 0177 const QString remoteDeviceNumber = dataMap[QLatin1String(NM_SSH_KEY_REMOTE_DEV)]; 0178 if (!remoteDeviceNumber.isEmpty()) { 0179 d->advUi.chk_remoteDeviceNumber->setChecked(true); 0180 d->advUi.sb_remoteDeviceNumber->setValue(remoteDeviceNumber.toInt()); 0181 } 0182 0183 const QString useTapDevice = dataMap[QLatin1String(NM_SSH_KEY_TAP_DEV)]; 0184 if (!useTapDevice.isEmpty()) { 0185 if (useTapDevice == QLatin1String("yes")) { 0186 d->advUi.chk_useTapDevice->setChecked(true); 0187 } 0188 } 0189 0190 const QString remoteUsername = dataMap[QLatin1String(NM_SSH_KEY_REMOTE_USERNAME)]; 0191 if (!remoteUsername.isEmpty()) { 0192 d->advUi.chk_remoteUsername->setChecked(true); 0193 d->advUi.le_remoteUsername->setText(remoteUsername); 0194 } 0195 0196 const QString doNotReplaceDefaultRoute = dataMap[QLatin1String(NM_SSH_KEY_NO_DEFAULT_ROUTE)]; 0197 if (!doNotReplaceDefaultRoute.isEmpty()) { 0198 if (doNotReplaceDefaultRoute == QLatin1String("yes")) { 0199 d->advUi.chk_doNotReplaceDefaultRoute->setChecked(true); 0200 } 0201 } 0202 0203 loadSecrets(setting); 0204 } 0205 0206 void SshSettingWidget::loadSecrets(const NetworkManager::Setting::Ptr &setting) 0207 { 0208 Q_D(SshSettingWidget); 0209 0210 NetworkManager::VpnSetting::Ptr vpnSetting = setting.staticCast<NetworkManager::VpnSetting>(); 0211 0212 if (vpnSetting) { 0213 const NMStringMap secrets = vpnSetting->secrets(); 0214 const QString keyPassword = secrets.value(NM_SSH_KEY_PASSWORD); 0215 if (!keyPassword.isEmpty()) { 0216 d->ui.le_password->setText(keyPassword); 0217 } 0218 } 0219 } 0220 0221 QVariantMap SshSettingWidget::setting() const 0222 { 0223 Q_D(const SshSettingWidget); 0224 0225 NetworkManager::VpnSetting setting; 0226 setting.setServiceType(QLatin1String(NM_DBUS_SERVICE_SSH)); 0227 0228 NMStringMap data; 0229 NMStringMap secretData; 0230 0231 data.insert(QLatin1String(NM_SSH_KEY_REMOTE), d->ui.le_gateway->text()); 0232 0233 if (!d->ui.le_remoteIp->text().isEmpty()) { 0234 data.insert(QLatin1String(NM_SSH_KEY_REMOTE_IP), d->ui.le_remoteIp->text()); 0235 } 0236 0237 if (!d->ui.le_localIp->text().isEmpty()) { 0238 data.insert(QLatin1String(NM_SSH_KEY_LOCAL_IP), d->ui.le_localIp->text()); 0239 } 0240 0241 if (!d->ui.le_netmask->text().isEmpty()) { 0242 data.insert(QLatin1String(NM_SSH_KEY_NETMASK), d->ui.le_netmask->text()); 0243 } 0244 0245 if (d->ui.chk_useIpv6->isChecked()) { 0246 data.insert(QLatin1String(NM_SSH_KEY_IP_6), QLatin1String("yes")); 0247 0248 if (!d->ui.le_remoteIpv6->text().isEmpty()) { 0249 data.insert(QLatin1String(NM_SSH_KEY_REMOTE_IP_6), d->ui.le_remoteIpv6->text()); 0250 } 0251 0252 if (!d->ui.le_localIpv6->text().isEmpty()) { 0253 data.insert(QLatin1String(NM_SSH_KEY_LOCAL_IP_6), d->ui.le_localIpv6->text()); 0254 } 0255 0256 if (!d->ui.le_netmaskIpv6->text().isEmpty()) { 0257 data.insert(QLatin1String(NM_SSH_KEY_NETMASK_6), d->ui.le_netmaskIpv6->text()); 0258 } 0259 } 0260 0261 switch (d->ui.cmb_authType->currentIndex()) { 0262 case 0: 0263 data.insert(QLatin1String(NM_SSH_KEY_AUTH_TYPE), QLatin1String(NM_SSH_AUTH_TYPE_SSH_AGENT)); 0264 break; 0265 case 1: 0266 data.insert(QLatin1String(NM_SSH_KEY_AUTH_TYPE), QLatin1String(NM_SSH_AUTH_TYPE_PASSWORD)); 0267 if (!d->ui.le_password->text().isEmpty()) { 0268 secretData.insert(QLatin1String(NM_SSH_KEY_PASSWORD), d->ui.le_password->text()); 0269 } 0270 handleOnePasswordType(d->ui.le_password, NM_SSH_KEY_PASSWORD "-flags", data); 0271 break; 0272 case 2: 0273 data.insert(QLatin1String(NM_SSH_KEY_AUTH_TYPE), QLatin1String(NM_SSH_AUTH_TYPE_KEY)); 0274 if (!d->ui.kurl_sshKeyFile->url().isEmpty()) { 0275 data.insert(QLatin1String(NM_SSH_KEY_KEY_FILE), d->ui.kurl_sshKeyFile->url().toLocalFile()); 0276 } 0277 break; 0278 } 0279 0280 if (d->advUi.chk_useCustomGatewayPort->isChecked()) { 0281 data.insert(QLatin1String(NM_SSH_KEY_PORT), QString::number(d->advUi.sb_useCustomGatewayPort->value())); 0282 } 0283 0284 if (d->advUi.chk_useCustomTunnelMtu->isChecked()) { 0285 data.insert(QLatin1String(NM_SSH_KEY_TUNNEL_MTU), QString::number(d->advUi.sb_useCustomTunnelMtu->value())); 0286 } 0287 0288 if (d->advUi.chk_extraSshOptions->isChecked()) { 0289 data.insert(QLatin1String(NM_SSH_KEY_EXTRA_OPTS), d->advUi.le_extraSshOptions->text()); 0290 } 0291 0292 if (d->advUi.chk_remoteDeviceNumber->isChecked()) { 0293 data.insert(QLatin1String(NM_SSH_KEY_REMOTE_DEV), QString::number(d->advUi.sb_remoteDeviceNumber->value())); 0294 } 0295 0296 if (d->advUi.chk_useTapDevice->isChecked()) { 0297 data.insert(QLatin1String(NM_SSH_KEY_TAP_DEV), QLatin1String("yes")); 0298 } 0299 0300 if (d->advUi.chk_remoteUsername->isChecked()) { 0301 data.insert(QLatin1String(NM_SSH_KEY_REMOTE_USERNAME), d->advUi.le_remoteUsername->text()); 0302 } 0303 0304 if (d->advUi.chk_doNotReplaceDefaultRoute->isChecked()) { 0305 data.insert(QLatin1String(NM_SSH_KEY_NO_DEFAULT_ROUTE), QLatin1String("yes")); 0306 } 0307 0308 // save it all 0309 setting.setData(data); 0310 setting.setSecrets(secretData); 0311 0312 return setting.toMap(); 0313 } 0314 0315 void SshSettingWidget::authTypeChanged(int index) 0316 { 0317 Q_D(SshSettingWidget); 0318 0319 if (index == 0) { 0320 d->ui.stackedWidget->setCurrentIndex(0); 0321 d->ui.passwordWidget->setVisible(false); 0322 } else if (index == 1) { 0323 d->ui.stackedWidget->setCurrentIndex(0); 0324 d->ui.passwordWidget->setVisible(true); 0325 } else { 0326 d->ui.stackedWidget->setCurrentIndex(1); 0327 } 0328 } 0329 0330 void SshSettingWidget::doAdvancedDialog() 0331 { 0332 Q_D(SshSettingWidget); 0333 d->advancedDlg->show(); 0334 } 0335 0336 void SshSettingWidget::passwordTypeChanged(int index) 0337 { 0338 Q_D(SshSettingWidget); 0339 d->ui.le_password->setEnabled(index == SettingWidget::EnumPasswordStorageType::Store); 0340 } 0341 0342 void SshSettingWidget::fillOnePasswordCombo(PasswordField *passwordField, NetworkManager::Setting::SecretFlags type) 0343 { 0344 if (type.testFlag(NetworkManager::Setting::None)) { 0345 passwordField->setPasswordOption(PasswordField::StoreForAllUsers); 0346 } else if (type.testFlag(NetworkManager::Setting::AgentOwned)) { 0347 passwordField->setPasswordOption(PasswordField::StoreForUser); 0348 } else if (type.testFlag(NetworkManager::Setting::NotSaved)) { 0349 passwordField->setPasswordOption(PasswordField::AlwaysAsk); 0350 } else { 0351 passwordField->setPasswordOption(PasswordField::PasswordField::NotRequired); 0352 } 0353 } 0354 0355 void SshSettingWidget::handleOnePasswordType(const PasswordField *passwordField, const QString &key, NMStringMap &data) const 0356 { 0357 const PasswordField::PasswordOption option = passwordField->passwordOption(); 0358 switch (option) { 0359 case PasswordField::StoreForAllUsers: 0360 data.insert(key, QString::number(NetworkManager::Setting::None)); 0361 break; 0362 case PasswordField::StoreForUser: 0363 data.insert(key, QString::number(NetworkManager::Setting::AgentOwned)); 0364 break; 0365 case PasswordField::AlwaysAsk: 0366 data.insert(key, QString::number(NetworkManager::Setting::NotSaved)); 0367 break; 0368 case PasswordField::NotRequired: 0369 data.insert(key, QString::number(NetworkManager::Setting::NotRequired)); 0370 break; 0371 } 0372 } 0373 0374 bool SshSettingWidget::isValid() const 0375 { 0376 Q_D(const SshSettingWidget); 0377 0378 return !d->ui.le_gateway->text().isEmpty() && !d->ui.le_localIp->text().isEmpty() && !d->ui.le_remoteIp->text().isEmpty() 0379 && !d->ui.le_netmask->text().isEmpty(); 0380 }