File indexing completed on 2024-04-21 16:20:26
0001 /* 0002 SPDX-FileCopyrightText: 2013 Lukas Tinkl <ltinkl@redhat.com> 0003 SPDX-FileCopyrightText: 2015 Jan Grulich <jgrulich@redhat.com> 0004 0005 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 #include "openvpnadvancedwidget.h" 0009 #include "nm-openvpn-service.h" 0010 #include "settingwidget.h" 0011 #include "ui_openvpnadvanced.h" 0012 0013 #include <QComboBox> 0014 #include <QStandardPaths> 0015 #include <QUrl> 0016 0017 #include <KAcceleratorManager> 0018 #include <KLocalizedString> 0019 #include <KProcess> 0020 0021 class OpenVpnAdvancedWidget::Private 0022 { 0023 public: 0024 NetworkManager::VpnSetting::Ptr setting; 0025 KProcess *openvpnCipherProcess = nullptr; 0026 KProcess *openvpnVersionProcess = nullptr; 0027 QByteArray openvpnCiphers; 0028 QByteArray openVpnVersion; 0029 bool gotOpenVpnCiphers = false; 0030 bool gotOpenVpnVersion = false; 0031 bool readConfig = false; 0032 int versionX = 0; 0033 int versionY = 0; 0034 int versionZ = 0; 0035 0036 class EnumProxyType 0037 { 0038 public: 0039 enum ProxyType { NotRequired = 0, HTTP = 1, SOCKS = 2 }; 0040 }; 0041 class EnumHashingAlgorithms 0042 { 0043 public: 0044 enum HashingAlgorithms { Default = 0, None, Md4, Md5, Sha1, Sha224, Sha256, Sha384, Sha512, Ripemd160 }; 0045 }; 0046 class EnumCompression 0047 { 0048 public: 0049 enum Compression { None = 0, LZO, LZ4, LZ4v2, Adaptive, Automatic }; 0050 }; 0051 }; 0052 0053 OpenVpnAdvancedWidget::OpenVpnAdvancedWidget(const NetworkManager::VpnSetting::Ptr &setting, QWidget *parent) 0054 : QDialog(parent) 0055 , m_ui(new Ui::OpenVpnAdvancedWidget) 0056 , d(new Private) 0057 { 0058 m_ui->setupUi(this); 0059 0060 setWindowTitle(i18nc("@title: window advanced openvpn properties", "Advanced OpenVPN properties")); 0061 0062 d->setting = setting; 0063 0064 m_ui->proxyPassword->setPasswordOptionsEnabled(true); 0065 m_ui->proxyPassword->setPasswordNotRequiredEnabled(true); 0066 0067 connect(m_ui->cbCertCheck, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &OpenVpnAdvancedWidget::certCheckTypeChanged); 0068 connect(m_ui->cmbProxyType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &OpenVpnAdvancedWidget::proxyTypeChanged); 0069 connect(m_ui->cboTLSMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) { 0070 if (index == 0) { 0071 m_ui->kurlTlsAuthKey->setDisabled(true); 0072 m_ui->cboDirection->setDisabled(true); 0073 } else if (index == 1) { // TLS-Auth 0074 m_ui->kurlTlsAuthKey->setEnabled(true); 0075 m_ui->cboDirection->setEnabled(true); 0076 } else { // TLS-Crypt 0077 m_ui->kurlTlsAuthKey->setEnabled(true); 0078 m_ui->cboDirection->setDisabled(true); 0079 } 0080 }); 0081 0082 // start openVPN process and get its cipher list 0083 const QString openVpnBinary = QStandardPaths::findExecutable("openvpn", QStringList{"/sbin", "/usr/sbin"}); 0084 const QStringList ciphersArgs(QLatin1String("--show-ciphers")); 0085 const QStringList versionArgs(QLatin1String("--version")); 0086 0087 d->openvpnCipherProcess = new KProcess(this); 0088 d->openvpnCipherProcess->setOutputChannelMode(KProcess::OnlyStdoutChannel); 0089 d->openvpnCipherProcess->setReadChannel(QProcess::StandardOutput); 0090 connect(d->openvpnCipherProcess, &KProcess::errorOccurred, this, &OpenVpnAdvancedWidget::openVpnCipherError); 0091 connect(d->openvpnCipherProcess, &KProcess::readyReadStandardOutput, this, &OpenVpnAdvancedWidget::gotOpenVpnCipherOutput); 0092 connect(d->openvpnCipherProcess, QOverload<int, QProcess::ExitStatus>::of(&KProcess::finished), this, &OpenVpnAdvancedWidget::openVpnCipherFinished); 0093 d->openvpnCipherProcess->setProgram(openVpnBinary, ciphersArgs); 0094 0095 d->openvpnVersionProcess = new KProcess(this); 0096 d->openvpnVersionProcess->setOutputChannelMode(KProcess::OnlyStdoutChannel); 0097 d->openvpnVersionProcess->setReadChannel(QProcess::StandardOutput); 0098 connect(d->openvpnVersionProcess, &KProcess::errorOccurred, this, &OpenVpnAdvancedWidget::openVpnVersionError); 0099 connect(d->openvpnVersionProcess, &KProcess::readyReadStandardOutput, this, &OpenVpnAdvancedWidget::gotOpenVpnVersionOutput); 0100 connect(d->openvpnVersionProcess, QOverload<int, QProcess::ExitStatus>::of(&KProcess::finished), this, &OpenVpnAdvancedWidget::openVpnVersionFinished); 0101 d->openvpnVersionProcess->setProgram(openVpnBinary, versionArgs); 0102 0103 connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &OpenVpnAdvancedWidget::accept); 0104 connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &OpenVpnAdvancedWidget::reject); 0105 0106 KAcceleratorManager::manage(this); 0107 0108 if (d->setting) { 0109 loadConfig(); 0110 } 0111 } 0112 0113 OpenVpnAdvancedWidget::~OpenVpnAdvancedWidget() 0114 { 0115 delete d; 0116 } 0117 0118 void OpenVpnAdvancedWidget::init() 0119 { 0120 d->openvpnCipherProcess->start(); 0121 d->openvpnVersionProcess->start(); 0122 } 0123 0124 void OpenVpnAdvancedWidget::gotOpenVpnCipherOutput() 0125 { 0126 d->openvpnCiphers.append(d->openvpnCipherProcess->readAll()); 0127 } 0128 0129 void OpenVpnAdvancedWidget::openVpnCipherError(QProcess::ProcessError) 0130 { 0131 m_ui->cboCipher->removeItem(0); 0132 m_ui->cboCipher->addItem(i18nc("@item:inlistbox Item added when OpenVPN cipher lookup failed", "OpenVPN cipher lookup failed")); 0133 } 0134 0135 void OpenVpnAdvancedWidget::openVpnCipherFinished(int exitCode, QProcess::ExitStatus exitStatus) 0136 { 0137 m_ui->cboCipher->removeItem(0); 0138 if (!exitCode && exitStatus == QProcess::NormalExit) { 0139 m_ui->cboCipher->addItem(i18nc("@item::inlist Default openvpn cipher item", "Default")); 0140 const QList<QByteArray> rawOutputLines = d->openvpnCiphers.split('\n'); 0141 bool foundFirstSpace = false; 0142 for (const QByteArray &cipher : rawOutputLines) { 0143 if (cipher.length() == 0) { 0144 foundFirstSpace = true; 0145 } else if (foundFirstSpace) { 0146 m_ui->cboCipher->addItem(QString::fromLocal8Bit(cipher.left(cipher.indexOf(' ')))); 0147 } 0148 } 0149 0150 if (m_ui->cboCipher->count()) { 0151 m_ui->cboCipher->setEnabled(true); 0152 } else { 0153 m_ui->cboCipher->addItem(i18nc("@item:inlistbox Item added when OpenVPN cipher lookup failed", "No OpenVPN ciphers found")); 0154 } 0155 } else { 0156 m_ui->cboCipher->addItem(i18nc("@item:inlistbox Item added when OpenVPN cipher lookup failed", "OpenVPN cipher lookup failed")); 0157 } 0158 delete d->openvpnCipherProcess; 0159 d->openvpnCipherProcess = nullptr; 0160 d->openvpnCiphers = QByteArray(); 0161 d->gotOpenVpnCiphers = true; 0162 0163 if (d->readConfig) { 0164 const NMStringMap dataMap = d->setting->data(); 0165 if (dataMap.contains(NM_OPENVPN_KEY_CIPHER)) { 0166 m_ui->cboCipher->setCurrentIndex(m_ui->cboCipher->findText(dataMap.value(NM_OPENVPN_KEY_CIPHER))); 0167 } 0168 } 0169 } 0170 0171 void OpenVpnAdvancedWidget::gotOpenVpnVersionOutput() 0172 { 0173 d->openVpnVersion.append(d->openvpnVersionProcess->readAll()); 0174 } 0175 0176 void OpenVpnAdvancedWidget::openVpnVersionError(QProcess::ProcessError) 0177 { 0178 // We couldn't identify OpenVPN version so disable tls-remote 0179 disableLegacySubjectMatch(); 0180 } 0181 0182 void OpenVpnAdvancedWidget::openVpnVersionFinished(int exitCode, QProcess::ExitStatus exitStatus) 0183 { 0184 // OpenVPN returns 1 when you use "--help" and unfortunately returns 1 even when some error occurs 0185 if (exitCode == 1 && exitStatus == QProcess::NormalExit) { 0186 QStringList list = QString(d->openVpnVersion).split(QLatin1Char(' ')); 0187 if (list.count() > 2) { 0188 const QStringList versionList = list.at(1).split(QLatin1Char('.')); 0189 if (versionList.count() == 3) { 0190 d->versionX = versionList.at(0).toInt(); 0191 d->versionY = versionList.at(1).toInt(); 0192 d->versionZ = versionList.at(2).toInt(); 0193 0194 if (compareVersion(2, 4, 0) >= 0) { 0195 disableLegacySubjectMatch(); 0196 } 0197 } 0198 } 0199 } else { 0200 disableLegacySubjectMatch(); 0201 } 0202 0203 delete d->openvpnVersionProcess; 0204 d->openvpnVersionProcess = nullptr; 0205 d->openVpnVersion = QByteArray(); 0206 d->gotOpenVpnVersion = true; 0207 0208 if (d->readConfig) { 0209 const NMStringMap dataMap = d->setting->data(); 0210 if (dataMap.contains(NM_OPENVPN_KEY_TLS_REMOTE)) { 0211 m_ui->subjectMatch->setText(dataMap.value(NM_OPENVPN_KEY_TLS_REMOTE)); 0212 } 0213 } 0214 } 0215 0216 int OpenVpnAdvancedWidget::compareVersion(const int x, const int y, const int z) const 0217 { 0218 if (d->versionX == 0) { 0219 // Not valid version 0220 return -2; 0221 } 0222 0223 if (d->versionX > x) { 0224 return 1; 0225 } else if (d->versionX < x) { 0226 return -1; 0227 } else if (d->versionY > y) { 0228 return 1; 0229 } else if (d->versionY < y) { 0230 return -1; 0231 } else if (d->versionZ > z) { 0232 return 1; 0233 } else if (d->versionZ < z) { 0234 return -1; 0235 } 0236 return 0; 0237 } 0238 0239 void OpenVpnAdvancedWidget::disableLegacySubjectMatch() 0240 { 0241 m_ui->cbCertCheck->removeItem(CertCheckType::VerifySubjectPartially); 0242 } 0243 0244 void OpenVpnAdvancedWidget::loadConfig() 0245 { 0246 const NMStringMap dataMap = d->setting->data(); 0247 const NMStringMap secrets = d->setting->secrets(); 0248 0249 // Optional Settings 0250 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PORT))) { 0251 m_ui->chkCustomPort->setChecked(true); 0252 m_ui->sbCustomPort->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PORT)].toUInt()); 0253 } else { 0254 m_ui->chkCustomPort->setChecked(false); 0255 m_ui->sbCustomPort->setValue(1194); // Default value 0256 } 0257 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_TUNNEL_MTU))) { 0258 m_ui->chkMtu->setChecked(true); 0259 m_ui->sbMtu->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_TUNNEL_MTU)].toUInt()); 0260 } else { 0261 m_ui->chkMtu->setChecked(false); 0262 m_ui->sbMtu->setValue(1500); // Default value 0263 } 0264 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_FRAGMENT_SIZE))) { 0265 m_ui->chkCustomFragmentSize->setChecked(true); 0266 m_ui->sbCustomFragmentSize->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_FRAGMENT_SIZE)].toUInt()); 0267 } else { 0268 m_ui->chkCustomFragmentSize->setChecked(false); 0269 m_ui->sbCustomFragmentSize->setValue(1300); 0270 } 0271 0272 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_RENEG_SECONDS))) { 0273 m_ui->chkUseCustomReneg->setChecked(true); 0274 m_ui->sbCustomReneg->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_RENEG_SECONDS)].toUInt()); 0275 } else { 0276 m_ui->chkUseCustomReneg->setChecked(false); 0277 m_ui->sbCustomReneg->setValue(0); 0278 } 0279 0280 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_COMP_LZO))) { 0281 const QString compLzo = dataMap[QLatin1String(NM_OPENVPN_KEY_COMP_LZO)]; 0282 if (compLzo == QLatin1String("no-by-default")) { 0283 m_ui->cmbUseCompression->setCurrentIndex(Private::EnumCompression::None); 0284 } else if (compLzo == QLatin1String("yes")) { 0285 m_ui->cmbUseCompression->setCurrentIndex(Private::EnumCompression::LZO); 0286 } else { 0287 m_ui->cmbUseCompression->setCurrentIndex(Private::EnumCompression::Adaptive); 0288 } 0289 m_ui->chkUseCompression->setChecked(true); 0290 } 0291 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_COMPRESS))) { 0292 const QString compress = dataMap[QLatin1String(NM_OPENVPN_KEY_COMPRESS)]; 0293 if (compress == QLatin1String("lz4")) { 0294 m_ui->cmbUseCompression->setCurrentIndex(Private::EnumCompression::LZ4); 0295 } else if (compress == QLatin1String("lz4-v2")) { 0296 m_ui->cmbUseCompression->setCurrentIndex(Private::EnumCompression::LZ4v2); 0297 } else if (compress == QLatin1String("lzo")) { 0298 m_ui->cmbUseCompression->setCurrentIndex(Private::EnumCompression::LZO); 0299 } else if (compress == QLatin1String("yes")) { 0300 m_ui->cmbUseCompression->setCurrentIndex(Private::EnumCompression::Automatic); 0301 } else { 0302 m_ui->cmbUseCompression->setCurrentIndex(Private::EnumCompression::Automatic); 0303 } 0304 m_ui->chkUseCompression->setChecked(true); 0305 } 0306 m_ui->chkUseTCP->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_PROTO_TCP)] == QLatin1String("yes")); 0307 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_DEV_TYPE))) { 0308 m_ui->chkUseVirtualDeviceType->setChecked(true); 0309 if (dataMap[QLatin1String(NM_OPENVPN_KEY_DEV_TYPE)] == QLatin1String("tap")) { 0310 m_ui->cmbDeviceType->setCurrentIndex(1); 0311 } 0312 } 0313 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_DEV))) { 0314 m_ui->chkUseVirtualDeviceName->setChecked(true); 0315 m_ui->leVirtualDeviceName->setText(dataMap[QLatin1String(NM_OPENVPN_KEY_DEV)]); 0316 } 0317 m_ui->chkMssRestrict->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_MSSFIX)] == QLatin1String("yes")); 0318 m_ui->chkRandRemHosts->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_REMOTE_RANDOM)] == QLatin1String("yes")); 0319 0320 m_ui->chkIpv6TunLink->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_TUN_IPV6)] == QLatin1String("yes")); 0321 0322 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PING))) { 0323 m_ui->chkPingInterval->setChecked(true); 0324 m_ui->sbPingInterval->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PING)].toInt()); 0325 } 0326 0327 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PING_EXIT)) || dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PING_RESTART))) { 0328 m_ui->chkSpecifyExitRestartPing->setChecked(true); 0329 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PING_EXIT))) { 0330 m_ui->cbSpecifyExitRestartPing->setCurrentIndex(0); // Exit 0331 m_ui->sbSpecifyExitRestartPing->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PING_EXIT)].toInt()); 0332 } else { 0333 m_ui->cbSpecifyExitRestartPing->setCurrentIndex(1); // Restart 0334 m_ui->sbSpecifyExitRestartPing->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PING_RESTART)].toInt()); 0335 } 0336 } 0337 0338 m_ui->chkAcceptAuthenticatedPackets->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_FLOAT)] == QLatin1String("yes")); 0339 0340 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_MAX_ROUTES))) { 0341 m_ui->chkMaxRoutes->setChecked(true); 0342 m_ui->sbMaxRoutes->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_MAX_ROUTES)].toInt()); 0343 } 0344 0345 // Optional Security Settings 0346 const QString hmacKeyAuth = dataMap[QLatin1String(NM_OPENVPN_KEY_AUTH)]; 0347 if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_NONE)) { 0348 m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::None); 0349 } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_RSA_MD4)) { 0350 m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Md4); 0351 } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_MD5)) { 0352 m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Md5); 0353 } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA1)) { 0354 m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha1); 0355 } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA224)) { 0356 m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha224); 0357 } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA256)) { 0358 m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha256); 0359 } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA384)) { 0360 m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha384); 0361 } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_SHA512)) { 0362 m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Sha512); 0363 } else if (hmacKeyAuth == QLatin1String(NM_OPENVPN_AUTH_RIPEMD160)) { 0364 m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Ripemd160); 0365 } else { 0366 m_ui->cboHmac->setCurrentIndex(Private::EnumHashingAlgorithms::Default); 0367 } 0368 0369 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_KEYSIZE))) { 0370 m_ui->chkUseCustomCipherKey->setChecked(true); 0371 m_ui->sbCustomCipherKey->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_KEYSIZE)].toUInt()); 0372 } 0373 0374 // ciphers populated above? 0375 if (d->gotOpenVpnCiphers && dataMap.contains(QLatin1String(NM_OPENVPN_KEY_CIPHER))) { 0376 m_ui->cboCipher->setCurrentIndex(m_ui->cboCipher->findText(dataMap[QLatin1String(NM_OPENVPN_KEY_CIPHER)])); 0377 } 0378 0379 // Optional TLS 0380 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_TLS_REMOTE))) { 0381 m_ui->cbCertCheck->setCurrentIndex(CertCheckType::VerifySubjectPartially); 0382 m_ui->subjectMatch->setText(dataMap[QLatin1String(NM_OPENVPN_KEY_TLS_REMOTE)]); 0383 } 0384 0385 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME))) { 0386 const QString x509Value = dataMap.value(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME)); 0387 const QStringList x509List = x509Value.split(QLatin1Char(':')); 0388 if (x509List.size() == 2) { 0389 if (x509List.at(0) == QLatin1String(NM_OPENVPN_VERIFY_X509_NAME_TYPE_SUBJECT)) { 0390 m_ui->cbCertCheck->setCurrentIndex(CertCheckType::VerifyWholeSubjectExactly); 0391 } else if (x509List.at(0) == QLatin1String(NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME)) { 0392 m_ui->cbCertCheck->setCurrentIndex(CertCheckType::VerifyNameExactly); 0393 } else if (x509List.at(0) == QLatin1String(NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME_PREFIX)) { 0394 m_ui->cbCertCheck->setCurrentIndex(CertCheckType::VerifyNameByPrefix); 0395 } 0396 m_ui->subjectMatch->setText(x509List.at(1)); 0397 } 0398 } else { 0399 m_ui->cbCertCheck->setCurrentIndex(CertCheckType::DontVerify); 0400 } 0401 0402 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_REMOTE_CERT_TLS))) { 0403 const QString remoteCertTls = dataMap[QLatin1String(NM_OPENVPN_KEY_REMOTE_CERT_TLS)]; 0404 m_ui->chkRemoteCertTls->setChecked(true); 0405 m_ui->labelRemoteCertTls->setEnabled(true); 0406 m_ui->cmbRemoteCertTls->setEnabled(true); 0407 m_ui->cmbRemoteCertTls->setCurrentIndex(remoteCertTls == QLatin1String(NM_OPENVPN_REM_CERT_TLS_SERVER) ? 0 : 1); 0408 } 0409 0410 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_NS_CERT_TYPE))) { 0411 const QString remoteCertTls = dataMap[QLatin1String(NM_OPENVPN_KEY_NS_CERT_TYPE)]; 0412 m_ui->chkNsCertType->setChecked(true); 0413 m_ui->lblNsCertType->setEnabled(true); 0414 m_ui->cmbNsCertType->setEnabled(true); 0415 m_ui->cmbNsCertType->setCurrentIndex(remoteCertTls == QLatin1String(NM_OPENVPN_NS_CERT_TYPE_SERVER) ? 0 : 1); 0416 } 0417 0418 const QString openvpnKeyTa = dataMap[QLatin1String(NM_OPENVPN_KEY_TA)]; 0419 const QString openvpnKeyTlsCrypt = dataMap[QLatin1String(NM_OPENVPN_KEY_TLS_CRYPT)]; 0420 0421 if (!openvpnKeyTlsCrypt.isEmpty()) { 0422 m_ui->cboTLSMode->setCurrentIndex(2); // TLS-Crypt 0423 m_ui->kurlTlsAuthKey->setUrl(QUrl::fromLocalFile(openvpnKeyTlsCrypt)); 0424 } else if (!openvpnKeyTa.isEmpty()) { 0425 m_ui->cboTLSMode->setCurrentIndex(1); // TLS-Auth 0426 m_ui->kurlTlsAuthKey->setUrl(QUrl::fromLocalFile(openvpnKeyTa)); 0427 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_TA_DIR))) { 0428 const uint tlsAuthDirection = dataMap[QLatin1String(NM_OPENVPN_KEY_TA_DIR)].toUInt(); 0429 m_ui->cboDirection->setCurrentIndex(tlsAuthDirection + 1); 0430 } 0431 } 0432 0433 // Proxies 0434 if (dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_TYPE)] == QLatin1String("http")) { 0435 m_ui->cmbProxyType->setCurrentIndex(Private::EnumProxyType::HTTP); 0436 } else if (dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_TYPE)] == QLatin1String("socks")) { 0437 m_ui->cmbProxyType->setCurrentIndex(Private::EnumProxyType::SOCKS); 0438 } else { 0439 m_ui->cmbProxyType->setCurrentIndex(Private::EnumProxyType::NotRequired); 0440 } 0441 proxyTypeChanged(m_ui->cmbProxyType->currentIndex()); 0442 m_ui->proxyServerAddress->setText(dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_SERVER)]); 0443 if (dataMap.contains(QLatin1String(NM_OPENVPN_KEY_PROXY_PORT))) { 0444 m_ui->sbProxyPort->setValue(dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_PORT)].toUInt()); 0445 } else { 0446 m_ui->sbProxyPort->setValue(0); 0447 } 0448 m_ui->chkProxyRetry->setChecked(dataMap[QLatin1String(NM_OPENVPN_KEY_PROXY_RETRY)] == QLatin1String("yes")); 0449 m_ui->proxyUsername->setText(dataMap[QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_USERNAME)]); 0450 d->readConfig = true; 0451 0452 NetworkManager::Setting::SecretFlags type; 0453 type = (NetworkManager::Setting::SecretFlags)dataMap[NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD "-flags"].toInt(); 0454 if (!(type & NetworkManager::Setting::NotSaved || type & NetworkManager::Setting::NotRequired)) { 0455 m_ui->proxyPassword->setText(secrets.value(QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD))); 0456 } 0457 fillOnePasswordCombo(m_ui->proxyPassword, type); 0458 } 0459 0460 void OpenVpnAdvancedWidget::fillOnePasswordCombo(PasswordField *passwordField, NetworkManager::Setting::SecretFlags type) 0461 { 0462 if (type.testFlag(NetworkManager::Setting::None)) { 0463 passwordField->setPasswordOption(PasswordField::StoreForAllUsers); 0464 } else if (type.testFlag(NetworkManager::Setting::AgentOwned)) { 0465 passwordField->setPasswordOption(PasswordField::StoreForUser); 0466 } else if (type.testFlag(NetworkManager::Setting::NotSaved)) { 0467 passwordField->setPasswordOption(PasswordField::AlwaysAsk); 0468 } else { 0469 passwordField->setPasswordOption(PasswordField::PasswordField::NotRequired); 0470 } 0471 } 0472 0473 NetworkManager::VpnSetting::Ptr OpenVpnAdvancedWidget::setting() const 0474 { 0475 NMStringMap data; 0476 NMStringMap secretData; 0477 0478 // optional settings 0479 if (m_ui->chkCustomPort->isChecked()) { 0480 data.insert(QLatin1String(NM_OPENVPN_KEY_PORT), QString::number(m_ui->sbCustomPort->value())); 0481 } 0482 if (m_ui->chkMtu->isChecked()) { 0483 data.insert(QLatin1String(NM_OPENVPN_KEY_TUNNEL_MTU), QString::number(m_ui->sbMtu->value())); 0484 } 0485 if (m_ui->chkCustomFragmentSize->isChecked()) { 0486 data.insert(QLatin1String(NM_OPENVPN_KEY_FRAGMENT_SIZE), QString::number(m_ui->sbCustomFragmentSize->value())); 0487 } 0488 if (m_ui->chkUseCustomReneg->isChecked()) { 0489 data.insert(QLatin1String(NM_OPENVPN_KEY_RENEG_SECONDS), QString::number(m_ui->sbCustomReneg->value())); 0490 } 0491 data.insert(QLatin1String(NM_OPENVPN_KEY_PROTO_TCP), m_ui->chkUseTCP->isChecked() ? QLatin1String("yes") : QLatin1String("no")); 0492 0493 if (m_ui->chkUseCompression->isChecked()) { 0494 switch (m_ui->cmbUseCompression->currentIndex()) { 0495 case Private::EnumCompression::None: 0496 data.insert(QLatin1String(NM_OPENVPN_KEY_COMP_LZO), QLatin1String("no-by-default")); 0497 break; 0498 case Private::EnumCompression::LZO: 0499 data.insert(QLatin1String(NM_OPENVPN_KEY_COMPRESS), QLatin1String("lzo")); 0500 break; 0501 case Private::EnumCompression::LZ4: 0502 data.insert(QLatin1String(NM_OPENVPN_KEY_COMPRESS), QLatin1String("lz4")); 0503 break; 0504 case Private::EnumCompression::LZ4v2: 0505 data.insert(QLatin1String(NM_OPENVPN_KEY_COMPRESS), QLatin1String("lz4-v2")); 0506 break; 0507 case Private::EnumCompression::Adaptive: 0508 data.insert(QLatin1String(NM_OPENVPN_KEY_COMP_LZO), QLatin1String("adaptive")); 0509 break; 0510 case Private::EnumCompression::Automatic: 0511 data.insert(QLatin1String(NM_OPENVPN_KEY_COMPRESS), QLatin1String("yes")); 0512 break; 0513 } 0514 } 0515 0516 if (m_ui->chkUseVirtualDeviceType->isChecked()) { 0517 data.insert(QLatin1String(NM_OPENVPN_KEY_DEV_TYPE), m_ui->cmbDeviceType->currentIndex() == 0 ? QLatin1String("tun") : QLatin1String("tap")); 0518 } 0519 if (m_ui->chkUseVirtualDeviceName->isChecked()) { 0520 data.insert(QLatin1String(NM_OPENVPN_KEY_DEV), m_ui->leVirtualDeviceName->text()); 0521 } 0522 0523 data.insert(QLatin1String(NM_OPENVPN_KEY_MSSFIX), m_ui->chkMssRestrict->isChecked() ? QLatin1String("yes") : QLatin1String("no")); 0524 data.insert(QLatin1String(NM_OPENVPN_KEY_REMOTE_RANDOM), m_ui->chkRandRemHosts->isChecked() ? QLatin1String("yes") : QLatin1String("no")); 0525 data.insert(QLatin1String(NM_OPENVPN_KEY_TUN_IPV6), m_ui->chkIpv6TunLink->isChecked() ? QLatin1String("yes") : QLatin1String("no")); 0526 0527 if (m_ui->chkPingInterval->isChecked()) { 0528 data.insert(QLatin1String(NM_OPENVPN_KEY_PING), QString::number(m_ui->sbPingInterval->value())); 0529 } 0530 0531 if (m_ui->chkSpecifyExitRestartPing->isChecked()) { 0532 if (m_ui->cbSpecifyExitRestartPing->currentIndex() == 0) { // Exit 0533 data.insert(QLatin1String(NM_OPENVPN_KEY_PING_EXIT), QString::number(m_ui->sbSpecifyExitRestartPing->value())); 0534 } else { // Restart 0535 data.insert(QLatin1String(NM_OPENVPN_KEY_PING_RESTART), QString::number(m_ui->sbSpecifyExitRestartPing->value())); 0536 } 0537 } 0538 0539 data.insert(QLatin1String(NM_OPENVPN_KEY_FLOAT), m_ui->chkAcceptAuthenticatedPackets->isChecked() ? QLatin1String("yes") : QLatin1String("no")); 0540 0541 if (m_ui->chkMaxRoutes->isChecked()) { 0542 data.insert(QLatin1String(NM_OPENVPN_KEY_MAX_ROUTES), QString::number(m_ui->sbMaxRoutes->value())); 0543 } 0544 0545 // Optional Security 0546 switch (m_ui->cboHmac->currentIndex()) { 0547 case Private::EnumHashingAlgorithms::Default: 0548 break; 0549 case Private::EnumHashingAlgorithms::None: 0550 data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_NONE)); 0551 break; 0552 case Private::EnumHashingAlgorithms::Md4: 0553 data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_RSA_MD4)); 0554 break; 0555 case Private::EnumHashingAlgorithms::Md5: 0556 data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_MD5)); 0557 break; 0558 case Private::EnumHashingAlgorithms::Sha1: 0559 data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA1)); 0560 break; 0561 case Private::EnumHashingAlgorithms::Sha224: 0562 data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA224)); 0563 break; 0564 case Private::EnumHashingAlgorithms::Sha256: 0565 data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA256)); 0566 break; 0567 case Private::EnumHashingAlgorithms::Sha384: 0568 data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA384)); 0569 break; 0570 case Private::EnumHashingAlgorithms::Sha512: 0571 data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_SHA512)); 0572 break; 0573 case Private::EnumHashingAlgorithms::Ripemd160: 0574 data.insert(QLatin1String(NM_OPENVPN_KEY_AUTH), QLatin1String(NM_OPENVPN_AUTH_RIPEMD160)); 0575 break; 0576 } 0577 0578 if (m_ui->chkUseCustomCipherKey->isChecked()) { 0579 data.insert(QLatin1String(NM_OPENVPN_KEY_KEYSIZE), QString::number(m_ui->sbCustomCipherKey->value())); 0580 } 0581 0582 if (m_ui->cboCipher->currentIndex() != 0) { 0583 data.insert(QLatin1String(NM_OPENVPN_KEY_CIPHER), m_ui->cboCipher->currentText()); 0584 } 0585 0586 // optional tls authentication 0587 switch (m_ui->cbCertCheck->currentIndex()) { 0588 case CertCheckType::DontVerify: 0589 break; 0590 case CertCheckType::VerifyWholeSubjectExactly: 0591 data.insert(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME), 0592 QStringLiteral("%1:%2").arg(NM_OPENVPN_VERIFY_X509_NAME_TYPE_SUBJECT, m_ui->subjectMatch->text())); 0593 break; 0594 case CertCheckType::VerifyNameExactly: 0595 data.insert(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME), 0596 QStringLiteral("%1:%2").arg(NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME, m_ui->subjectMatch->text())); 0597 break; 0598 case CertCheckType::VerifyNameByPrefix: 0599 data.insert(QLatin1String(NM_OPENVPN_KEY_VERIFY_X509_NAME), 0600 QStringLiteral("%1:%2").arg(NM_OPENVPN_VERIFY_X509_NAME_TYPE_NAME_PREFIX, m_ui->subjectMatch->text())); 0601 break; 0602 case CertCheckType::VerifySubjectPartially: 0603 data.insert(QLatin1String(NM_OPENVPN_KEY_TLS_REMOTE), m_ui->subjectMatch->text()); 0604 break; 0605 } 0606 0607 if (m_ui->chkRemoteCertTls->isChecked()) { 0608 if (m_ui->cmbRemoteCertTls->currentIndex() == 0) { 0609 data.insert(QLatin1String(NM_OPENVPN_KEY_REMOTE_CERT_TLS), NM_OPENVPN_REM_CERT_TLS_SERVER); 0610 } else { 0611 data.insert(QLatin1String(NM_OPENVPN_KEY_REMOTE_CERT_TLS), NM_OPENVPN_REM_CERT_TLS_CLIENT); 0612 } 0613 } 0614 0615 if (m_ui->chkNsCertType->isChecked()) { 0616 if (m_ui->cmbNsCertType->currentIndex() == 0) { 0617 data.insert(QLatin1String(NM_OPENVPN_KEY_NS_CERT_TYPE), NM_OPENVPN_NS_CERT_TYPE_SERVER); 0618 } else { 0619 data.insert(QLatin1String(NM_OPENVPN_KEY_NS_CERT_TYPE), NM_OPENVPN_NS_CERT_TYPE_CLIENT); 0620 } 0621 } 0622 0623 if (m_ui->cboTLSMode->currentIndex() == 1) { // TLS-Auth 0624 QUrl tlsAuthKeyUrl = m_ui->kurlTlsAuthKey->url(); 0625 if (!tlsAuthKeyUrl.isEmpty()) { 0626 data.insert(QLatin1String(NM_OPENVPN_KEY_TA), tlsAuthKeyUrl.path()); 0627 } 0628 if (m_ui->cboDirection->currentIndex() > 0) { 0629 data.insert(QLatin1String(NM_OPENVPN_KEY_TA_DIR), QString::number(m_ui->cboDirection->currentIndex() - 1)); 0630 } 0631 } else if (m_ui->cboTLSMode->currentIndex() == 2) { // TLS-Crypt 0632 QUrl tlsCryptKeyUrl = m_ui->kurlTlsAuthKey->url(); 0633 if (!tlsCryptKeyUrl.isEmpty()) { 0634 data.insert(QLatin1String(NM_OPENVPN_KEY_TLS_CRYPT), tlsCryptKeyUrl.path()); 0635 } 0636 } 0637 0638 // Proxies 0639 switch (m_ui->cmbProxyType->currentIndex()) { 0640 case Private::EnumProxyType::NotRequired: 0641 break; 0642 case Private::EnumProxyType::HTTP: 0643 data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_TYPE), QLatin1String("http")); 0644 data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_SERVER), m_ui->proxyServerAddress->text()); 0645 data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_PORT), QString::number(m_ui->sbProxyPort->value())); 0646 data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_RETRY), m_ui->chkProxyRetry->isChecked() ? QLatin1String("yes") : QLatin1String("no")); 0647 if (!m_ui->proxyUsername->text().isEmpty()) { 0648 data.insert(QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_USERNAME), m_ui->proxyUsername->text()); 0649 secretData.insert(QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD), m_ui->proxyPassword->text()); 0650 handleOnePasswordType(m_ui->proxyPassword, QLatin1String(NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD "-flags"), data); 0651 } 0652 break; 0653 case Private::EnumProxyType::SOCKS: 0654 data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_TYPE), QLatin1String("socks")); 0655 data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_SERVER), m_ui->proxyServerAddress->text()); 0656 data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_PORT), QString::number(m_ui->sbProxyPort->value())); 0657 data.insert(QLatin1String(NM_OPENVPN_KEY_PROXY_RETRY), m_ui->chkProxyRetry->isChecked() ? QLatin1String("yes") : QLatin1String("no")); 0658 break; 0659 } 0660 0661 d->setting->setData(data); 0662 d->setting->setSecrets(secretData); 0663 0664 return d->setting; 0665 } 0666 0667 void OpenVpnAdvancedWidget::certCheckTypeChanged(int type) 0668 { 0669 if (type == CertCheckType::DontVerify) { 0670 m_ui->lbSubjectMatch->setEnabled(false); 0671 m_ui->subjectMatch->setEnabled(false); 0672 } else { 0673 m_ui->lbSubjectMatch->setEnabled(true); 0674 m_ui->subjectMatch->setEnabled(true); 0675 } 0676 } 0677 0678 void OpenVpnAdvancedWidget::proxyTypeChanged(int type) 0679 { 0680 switch (type) { 0681 case Private::EnumProxyType::NotRequired: 0682 m_ui->proxyServerAddress->setEnabled(false); 0683 m_ui->sbProxyPort->setEnabled(false); 0684 m_ui->chkProxyRetry->setEnabled(false); 0685 m_ui->proxyUsername->setEnabled(false); 0686 m_ui->proxyPassword->setEnabled(false); 0687 break; 0688 case Private::EnumProxyType::HTTP: 0689 m_ui->proxyServerAddress->setEnabled(true); 0690 m_ui->sbProxyPort->setEnabled(true); 0691 m_ui->chkProxyRetry->setEnabled(true); 0692 m_ui->proxyUsername->setEnabled(true); 0693 m_ui->proxyPassword->setEnabled(true); 0694 break; 0695 case Private::EnumProxyType::SOCKS: 0696 m_ui->proxyServerAddress->setEnabled(true); 0697 m_ui->sbProxyPort->setEnabled(true); 0698 m_ui->chkProxyRetry->setEnabled(true); 0699 m_ui->proxyUsername->setEnabled(false); 0700 m_ui->proxyPassword->setEnabled(false); 0701 break; 0702 } 0703 } 0704 0705 void OpenVpnAdvancedWidget::handleOnePasswordType(const PasswordField *passwordField, const QString &key, NMStringMap &data) const 0706 { 0707 const PasswordField::PasswordOption option = passwordField->passwordOption(); 0708 switch (option) { 0709 case PasswordField::StoreForAllUsers: 0710 data.insert(key, QString::number(NetworkManager::Setting::None)); 0711 break; 0712 case PasswordField::StoreForUser: 0713 data.insert(key, QString::number(NetworkManager::Setting::AgentOwned)); 0714 break; 0715 case PasswordField::AlwaysAsk: 0716 data.insert(key, QString::number(NetworkManager::Setting::NotSaved)); 0717 break; 0718 case PasswordField::NotRequired: 0719 data.insert(key, QString::number(NetworkManager::Setting::NotRequired)); 0720 break; 0721 } 0722 }