File indexing completed on 2024-07-21 07:58:05

0001 /*
0002     SPDX-FileCopyrightText: 2013 Lukas Tinkl <ltinkl@redhat.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "security802-1x.h"
0008 #include "editlistdialog.h"
0009 #include "listvalidator.h"
0010 #include "ui_802-1x.h"
0011 
0012 #include <KAcceleratorManager>
0013 #include <KLocalizedString>
0014 
0015 #include <QtCrypto>
0016 
0017 Security8021x::Security8021x(const NetworkManager::Setting::Ptr &setting, Type type, QWidget *parent, Qt::WindowFlags f)
0018     : SettingWidget(setting, parent, f)
0019     , m_setting(setting.staticCast<NetworkManager::Security8021xSetting>())
0020     , m_ui(new Ui::Security8021x)
0021 {
0022     m_ui->setupUi(this);
0023 
0024     m_ui->fastPassword->setPasswordOptionsEnabled(true);
0025     m_ui->leapPassword->setPasswordOptionsEnabled(true);
0026     m_ui->md5Password->setPasswordOptionsEnabled(true);
0027     m_ui->peapPassword->setPasswordOptionsEnabled(true);
0028     m_ui->pwdPassword->setPasswordOptionsEnabled(true);
0029     m_ui->tlsPrivateKeyPassword->setPasswordOptionsEnabled(true);
0030     m_ui->ttlsPassword->setPasswordOptionsEnabled(true);
0031 
0032     if (type == WirelessWpaEap) {
0033         m_ui->auth->removeItem(0); // MD 5
0034         m_ui->stackedWidget->removeWidget(m_ui->md5Page);
0035 
0036         m_ui->auth->setItemData(0, NetworkManager::Security8021xSetting::EapMethodTls);
0037         m_ui->auth->setItemData(1, NetworkManager::Security8021xSetting::EapMethodLeap);
0038         m_ui->auth->setItemData(2, NetworkManager::Security8021xSetting::EapMethodPwd);
0039         m_ui->auth->setItemData(3, NetworkManager::Security8021xSetting::EapMethodFast);
0040         m_ui->auth->setItemData(4, NetworkManager::Security8021xSetting::EapMethodTtls);
0041         m_ui->auth->setItemData(5, NetworkManager::Security8021xSetting::EapMethodPeap);
0042     } else if (type == WirelessWpaEapSuiteB192) {
0043         // Remove all methods except TLS
0044         m_ui->auth->removeItem(6); // Protected EAP (PEAP)
0045         m_ui->auth->removeItem(5); // Tunneled TLS (TTLS)
0046         m_ui->auth->removeItem(4); // FAST
0047         m_ui->auth->removeItem(3); // PWD
0048         m_ui->auth->removeItem(2); // LEAP
0049         m_ui->auth->removeItem(0); // MD5
0050         m_ui->stackedWidget->removeWidget(m_ui->peapPage);
0051         m_ui->stackedWidget->removeWidget(m_ui->ttlsPage);
0052         m_ui->stackedWidget->removeWidget(m_ui->fastPage);
0053         m_ui->stackedWidget->removeWidget(m_ui->pwdPage);
0054         m_ui->stackedWidget->removeWidget(m_ui->leapPage);
0055         m_ui->stackedWidget->removeWidget(m_ui->md5Page);
0056 
0057         m_ui->auth->setItemData(0, NetworkManager::Security8021xSetting::EapMethodTls);
0058     } else {
0059         m_ui->auth->removeItem(2); // LEAP
0060         m_ui->stackedWidget->removeWidget(m_ui->leapPage);
0061 
0062         m_ui->auth->setItemData(0, NetworkManager::Security8021xSetting::EapMethodMd5);
0063         m_ui->auth->setItemData(1, NetworkManager::Security8021xSetting::EapMethodTls);
0064         m_ui->auth->setItemData(2, NetworkManager::Security8021xSetting::EapMethodPwd);
0065         m_ui->auth->setItemData(3, NetworkManager::Security8021xSetting::EapMethodFast);
0066         m_ui->auth->setItemData(4, NetworkManager::Security8021xSetting::EapMethodTtls);
0067         m_ui->auth->setItemData(5, NetworkManager::Security8021xSetting::EapMethodPeap);
0068     }
0069 
0070     if (type == WirelessWpaEapSuiteB192) {
0071         // Set TLS authentication as default
0072         m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodTls));
0073     } else {
0074         // Set PEAP authentication as default
0075         m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodPeap));
0076     }
0077 
0078     connect(m_ui->btnTlsAltSubjectMatches, &QPushButton::clicked, this, &Security8021x::altSubjectMatchesButtonClicked);
0079     connect(m_ui->btnTlsConnectToServers, &QPushButton::clicked, this, &Security8021x::connectToServersButtonClicked);
0080 
0081     // Connect for setting check
0082     watchChangedSetting();
0083 
0084     // Connect for validity check
0085     connect(m_ui->auth, QOverload<int>::of(&KComboBox::currentIndexChanged), this, &Security8021x::slotWidgetChanged);
0086     connect(m_ui->md5UserName, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged);
0087     connect(m_ui->md5Password, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged);
0088     connect(m_ui->md5Password, &PasswordField::passwordOptionChanged, this, &Security8021x::slotWidgetChanged);
0089     connect(m_ui->tlsIdentity, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged);
0090     connect(m_ui->tlsCACert, &KUrlRequester::textChanged, this, &Security8021x::slotWidgetChanged);
0091     connect(m_ui->tlsUserCert, &KUrlRequester::textChanged, this, &Security8021x::slotWidgetChanged);
0092     connect(m_ui->tlsPrivateKey, &KUrlRequester::textChanged, this, &Security8021x::slotWidgetChanged);
0093     connect(m_ui->tlsPrivateKeyPassword, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged);
0094     connect(m_ui->tlsPrivateKeyPassword, &PasswordField::passwordOptionChanged, this, &Security8021x::slotWidgetChanged);
0095     connect(m_ui->leapUsername, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged);
0096     connect(m_ui->leapPassword, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged);
0097     connect(m_ui->leapPassword, &PasswordField::passwordOptionChanged, this, &Security8021x::slotWidgetChanged);
0098     connect(m_ui->fastAllowPacProvisioning, &QCheckBox::stateChanged, this, &Security8021x::slotWidgetChanged);
0099     connect(m_ui->pacFile, &KUrlRequester::textChanged, this, &Security8021x::slotWidgetChanged);
0100     connect(m_ui->pwdUsername, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged);
0101     connect(m_ui->pwdPassword, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged);
0102     connect(m_ui->fastUsername, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged);
0103     connect(m_ui->fastPassword, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged);
0104     connect(m_ui->fastPassword, &PasswordField::passwordOptionChanged, this, &Security8021x::slotWidgetChanged);
0105     connect(m_ui->ttlsCACert, &KUrlRequester::textChanged, this, &Security8021x::slotWidgetChanged);
0106     connect(m_ui->ttlsUsername, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged);
0107     connect(m_ui->ttlsPassword, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged);
0108     connect(m_ui->ttlsPassword, &PasswordField::passwordOptionChanged, this, &Security8021x::slotWidgetChanged);
0109     connect(m_ui->peapCACert, &KUrlRequester::textChanged, this, &Security8021x::slotWidgetChanged);
0110     connect(m_ui->peapUsername, &KLineEdit::textChanged, this, &Security8021x::slotWidgetChanged);
0111     connect(m_ui->peapPassword, &PasswordField::textChanged, this, &Security8021x::slotWidgetChanged);
0112     connect(m_ui->peapPassword, &PasswordField::passwordOptionChanged, this, &Security8021x::slotWidgetChanged);
0113 
0114     KAcceleratorManager::manage(this);
0115     connect(m_ui->stackedWidget, &QStackedWidget::currentChanged, this, &Security8021x::currentAuthChanged);
0116 
0117     altSubjectValidator = new QRegularExpressionValidator(
0118         QRegularExpression(
0119             QLatin1String("^(DNS:[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_.-]+|EMAIL:[a-zA-Z0-9._-]+@[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_.-]+|URI:[a-zA-Z0-9.+-]+:.+|)$")),
0120         this);
0121     serversValidator = new QRegularExpressionValidator(QRegularExpression(QLatin1String("^[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_.-]+$")), this);
0122 
0123     auto altSubjectListValidator = new ListValidator(this);
0124     altSubjectListValidator->setInnerValidator(altSubjectValidator);
0125     m_ui->leTlsSubjectMatch->setValidator(altSubjectListValidator);
0126 
0127     auto serverListValidator = new ListValidator(this);
0128     serverListValidator->setInnerValidator(serversValidator);
0129     m_ui->leTlsConnectToServers->setValidator(serverListValidator);
0130 
0131     if (setting) {
0132         loadConfig(setting);
0133     }
0134 }
0135 
0136 Security8021x::~Security8021x()
0137 {
0138     delete m_ui;
0139 }
0140 
0141 void Security8021x::loadConfig(const NetworkManager::Setting::Ptr &setting)
0142 {
0143     NetworkManager::Security8021xSetting::Ptr securitySetting = setting.staticCast<NetworkManager::Security8021xSetting>();
0144 
0145     const QList<NetworkManager::Security8021xSetting::EapMethod> eapMethods = securitySetting->eapMethods();
0146     const NetworkManager::Security8021xSetting::AuthMethod phase2AuthMethod = securitySetting->phase2AuthMethod();
0147 
0148     if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::None)) {
0149         setPasswordOption(PasswordField::StoreForAllUsers);
0150     } else if (securitySetting->passwordFlags().testFlag(NetworkManager::Setting::AgentOwned)) {
0151         setPasswordOption(PasswordField::StoreForUser);
0152     } else {
0153         setPasswordOption(PasswordField::AlwaysAsk);
0154     }
0155 
0156     if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodMd5)) {
0157         m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodMd5));
0158         m_ui->md5UserName->setText(securitySetting->identity());
0159     } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodTls)) {
0160         QStringList servers;
0161         m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodTls));
0162         m_ui->tlsIdentity->setText(securitySetting->identity());
0163         m_ui->tlsDomain->setText(securitySetting->domainSuffixMatch());
0164         m_ui->tlsUserCert->setUrl(QUrl::fromLocalFile(securitySetting->clientCertificate()));
0165         m_ui->tlsCACert->setUrl(QUrl::fromLocalFile(securitySetting->caCertificate()));
0166         m_ui->leTlsSubjectMatch->setText(securitySetting->subjectMatch());
0167         m_ui->leTlsAlternativeSubjectMatches->setText(securitySetting->altSubjectMatches().join(QLatin1String(", ")));
0168         for (const QString &match : securitySetting->altSubjectMatches()) {
0169             if (match.startsWith(QLatin1String("DNS:"))) {
0170                 servers.append(match.right(match.length() - 4));
0171             }
0172         }
0173         m_ui->leTlsConnectToServers->setText(servers.join(QLatin1String(", ")));
0174         m_ui->tlsPrivateKey->setUrl(QUrl::fromLocalFile(securitySetting->privateKey()));
0175     } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodLeap)) {
0176         m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodLeap));
0177         m_ui->leapUsername->setText(securitySetting->identity());
0178     } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodPwd)) {
0179         m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodPwd));
0180         m_ui->pwdUsername->setText(securitySetting->identity());
0181     } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodFast)) {
0182         m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodFast));
0183         m_ui->fastAnonIdentity->setText(securitySetting->anonymousIdentity());
0184         m_ui->fastAllowPacProvisioning->setChecked((int)securitySetting->phase1FastProvisioning() > 0);
0185         m_ui->pacMethod->setCurrentIndex(securitySetting->phase1FastProvisioning() - 1);
0186         m_ui->pacFile->setUrl(QUrl::fromLocalFile(securitySetting->pacFile()));
0187         if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodGtc) {
0188             m_ui->fastInnerAuth->setCurrentIndex(0);
0189         } else {
0190             m_ui->fastInnerAuth->setCurrentIndex(1);
0191         }
0192         m_ui->fastUsername->setText(securitySetting->identity());
0193     } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodTtls)) {
0194         m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodTtls));
0195         m_ui->ttlsAnonIdentity->setText(securitySetting->anonymousIdentity());
0196         m_ui->ttlsDomain->setText(securitySetting->domainSuffixMatch());
0197         m_ui->ttlsCACert->setUrl(QUrl::fromLocalFile(securitySetting->caCertificate()));
0198         if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodPap) {
0199             m_ui->ttlsInnerAuth->setCurrentIndex(0);
0200         } else if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodMschap) {
0201             m_ui->ttlsInnerAuth->setCurrentIndex(1);
0202         } else if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodMschapv2) {
0203             m_ui->ttlsInnerAuth->setCurrentIndex(2);
0204         } else if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodChap) {
0205             m_ui->ttlsInnerAuth->setCurrentIndex(3);
0206         }
0207         m_ui->ttlsUsername->setText(securitySetting->identity());
0208     } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodPeap)) {
0209         m_ui->auth->setCurrentIndex(m_ui->auth->findData(NetworkManager::Security8021xSetting::EapMethodPeap));
0210         m_ui->peapAnonIdentity->setText(securitySetting->anonymousIdentity());
0211         m_ui->peapDomain->setText(securitySetting->domainSuffixMatch());
0212         m_ui->peapCACert->setUrl(QUrl::fromLocalFile(securitySetting->caCertificate()));
0213         m_ui->peapVersion->setCurrentIndex(securitySetting->phase1PeapVersion() + 1);
0214         if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodMschapv2) {
0215             m_ui->peapInnerAuth->setCurrentIndex(0);
0216         } else if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodMd5) {
0217             m_ui->peapInnerAuth->setCurrentIndex(1);
0218         } else if (phase2AuthMethod == NetworkManager::Security8021xSetting::AuthMethodGtc) {
0219             m_ui->peapInnerAuth->setCurrentIndex(2);
0220         }
0221         m_ui->peapUsername->setText(securitySetting->identity());
0222     }
0223 
0224     loadSecrets(setting);
0225 }
0226 
0227 void Security8021x::loadSecrets(const NetworkManager::Setting::Ptr &setting)
0228 {
0229     NetworkManager::Security8021xSetting::Ptr securitySetting = setting.staticCast<NetworkManager::Security8021xSetting>();
0230 
0231     const QString password = securitySetting->password();
0232     const QList<NetworkManager::Security8021xSetting::EapMethod> eapMethods = securitySetting->eapMethods();
0233 
0234     if (!password.isEmpty()) {
0235         if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodMd5)) {
0236             m_ui->md5Password->setText(securitySetting->password());
0237         } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodLeap)) {
0238             m_ui->leapPassword->setText(securitySetting->password());
0239         } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodFast)) {
0240             m_ui->fastPassword->setText(securitySetting->password());
0241         } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodPwd)) {
0242             m_ui->pwdPassword->setText(securitySetting->password());
0243         } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodTtls)) {
0244             m_ui->ttlsPassword->setText(securitySetting->password());
0245         } else if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodPeap)) {
0246             m_ui->peapPassword->setText(securitySetting->password());
0247         }
0248     }
0249 
0250     if (eapMethods.contains(NetworkManager::Security8021xSetting::EapMethodTls)) {
0251         const QString privateKeyPassword = securitySetting->privateKeyPassword();
0252         if (!privateKeyPassword.isEmpty()) {
0253             m_ui->tlsPrivateKeyPassword->setText(securitySetting->privateKeyPassword());
0254         }
0255     }
0256 }
0257 
0258 QVariantMap Security8021x::setting() const
0259 {
0260     NetworkManager::Security8021xSetting setting;
0261 
0262     NetworkManager::Security8021xSetting::EapMethod method =
0263         static_cast<NetworkManager::Security8021xSetting::EapMethod>(m_ui->auth->itemData(m_ui->auth->currentIndex()).toInt());
0264 
0265     setting.setEapMethods(QList<NetworkManager::Security8021xSetting::EapMethod>() << method);
0266 
0267     if (method == NetworkManager::Security8021xSetting::EapMethodMd5) {
0268         if (!m_ui->md5UserName->text().isEmpty()) {
0269             setting.setIdentity(m_ui->md5UserName->text());
0270         }
0271 
0272         if (m_ui->md5Password->passwordOption() == PasswordField::StoreForAllUsers) {
0273             setting.setPasswordFlags(NetworkManager::Setting::None);
0274         } else if (m_ui->md5Password->passwordOption() == PasswordField::StoreForUser) {
0275             setting.setPasswordFlags(NetworkManager::Setting::AgentOwned);
0276         } else {
0277             setting.setPasswordFlags(NetworkManager::Setting::NotSaved);
0278         }
0279 
0280         if (!m_ui->md5Password->text().isEmpty()) {
0281             setting.setPassword(m_ui->md5Password->text());
0282         }
0283     } else if (method == NetworkManager::Security8021xSetting::EapMethodTls) {
0284         if (!m_ui->tlsIdentity->text().isEmpty()) {
0285             setting.setIdentity(m_ui->tlsIdentity->text());
0286         }
0287 
0288         if (!m_ui->tlsDomain->text().isEmpty()) {
0289             setting.setDomainSuffixMatch(m_ui->tlsDomain->text());
0290         }
0291 
0292         if (m_ui->tlsUserCert->url().isValid()) {
0293             setting.setClientCertificate(m_ui->tlsUserCert->url().toString().toUtf8().append('\0'));
0294         }
0295 
0296         if (m_ui->tlsCACert->url().isValid()) {
0297             setting.setCaCertificate(m_ui->tlsCACert->url().toString().toUtf8().append('\0'));
0298         }
0299 
0300         QStringList altsubjectmatches = m_ui->leTlsAlternativeSubjectMatches->text().remove(QLatin1Char(' ')).split(QLatin1Char(','), Qt::SkipEmptyParts);
0301         for (const QString &match : m_ui->leTlsConnectToServers->text().remove(QLatin1Char(' ')).split(QLatin1Char(','), Qt::SkipEmptyParts)) {
0302             const QString tempstr = QLatin1String("DNS:") + match;
0303             if (!altsubjectmatches.contains(tempstr)) {
0304                 altsubjectmatches.append(tempstr);
0305             }
0306         }
0307         setting.setSubjectMatch(m_ui->leTlsSubjectMatch->text());
0308         setting.setAltSubjectMatches(altsubjectmatches);
0309 
0310         if (m_ui->tlsPrivateKey->url().isValid()) {
0311             setting.setPrivateKey(m_ui->tlsPrivateKey->url().toString().toUtf8().append('\0'));
0312         }
0313 
0314         if (!m_ui->tlsPrivateKeyPassword->text().isEmpty()) {
0315             setting.setPrivateKeyPassword(m_ui->tlsPrivateKeyPassword->text());
0316         }
0317 
0318         QCA::Initializer init;
0319         QCA::ConvertResult convRes;
0320 
0321         // Try if the private key is in pkcs12 format bundled with client certificate
0322         if (QCA::isSupported("pkcs12")) {
0323             QCA::KeyBundle keyBundle = QCA::KeyBundle::fromFile(m_ui->tlsPrivateKey->url().path(), m_ui->tlsPrivateKeyPassword->text().toUtf8(), &convRes);
0324             // Set client certificate to the same path as private key
0325             if (convRes == QCA::ConvertGood && keyBundle.privateKey().canDecrypt()) {
0326                 setting.setClientCertificate(m_ui->tlsPrivateKey->url().toString().toUtf8().append('\0'));
0327             }
0328         }
0329 
0330         if (m_ui->tlsPrivateKeyPassword->passwordOption() == PasswordField::StoreForAllUsers) {
0331             setting.setPrivateKeyPasswordFlags(NetworkManager::Setting::None);
0332         } else if (m_ui->tlsPrivateKeyPassword->passwordOption() == PasswordField::StoreForUser) {
0333             setting.setPrivateKeyPasswordFlags(NetworkManager::Setting::AgentOwned);
0334         } else {
0335             setting.setPrivateKeyPasswordFlags(NetworkManager::Setting::NotSaved);
0336         }
0337     } else if (method == NetworkManager::Security8021xSetting::EapMethodLeap) {
0338         if (!m_ui->leapUsername->text().isEmpty()) {
0339             setting.setIdentity(m_ui->leapUsername->text());
0340         }
0341 
0342         if (!m_ui->leapPassword->text().isEmpty()) {
0343             setting.setPassword(m_ui->leapPassword->text());
0344         }
0345 
0346         if (m_ui->leapPassword->passwordOption() == PasswordField::StoreForAllUsers) {
0347             setting.setPasswordFlags(NetworkManager::Setting::None);
0348         } else if (m_ui->leapPassword->passwordOption() == PasswordField::StoreForUser) {
0349             setting.setPasswordFlags(NetworkManager::Setting::AgentOwned);
0350         } else {
0351             setting.setPasswordFlags(NetworkManager::Setting::NotSaved);
0352         }
0353     } else if (method == NetworkManager::Security8021xSetting::EapMethodPwd) {
0354         if (!m_ui->pwdUsername->text().isEmpty()) {
0355             setting.setIdentity(m_ui->pwdUsername->text());
0356         }
0357 
0358         if (m_ui->pwdPassword->passwordOption() == PasswordField::StoreForAllUsers) {
0359             setting.setPasswordFlags(NetworkManager::Setting::None);
0360         } else if (m_ui->pwdPassword->passwordOption() == PasswordField::StoreForUser) {
0361             setting.setPasswordFlags(NetworkManager::Setting::AgentOwned);
0362         } else {
0363             setting.setPasswordFlags(NetworkManager::Setting::NotSaved);
0364         }
0365 
0366         if (!m_ui->pwdPassword->text().isEmpty()) {
0367             setting.setPassword(m_ui->pwdPassword->text());
0368         }
0369     } else if (method == NetworkManager::Security8021xSetting::EapMethodFast) {
0370         if (!m_ui->fastAnonIdentity->text().isEmpty()) {
0371             setting.setAnonymousIdentity(m_ui->fastAnonIdentity->text());
0372         }
0373 
0374         if (!m_ui->fastAllowPacProvisioning->isChecked()) {
0375             setting.setPhase1FastProvisioning(NetworkManager::Security8021xSetting::FastProvisioningDisabled);
0376         } else {
0377             setting.setPhase1FastProvisioning(static_cast<NetworkManager::Security8021xSetting::FastProvisioning>(m_ui->pacMethod->currentIndex() + 1));
0378         }
0379 
0380         if (m_ui->pacFile->url().isValid()) {
0381             setting.setPacFile(QFile::encodeName(m_ui->pacFile->url().toLocalFile()));
0382         }
0383 
0384         if (m_ui->fastInnerAuth->currentIndex() == 0) {
0385             setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodGtc);
0386         } else {
0387             setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodMschapv2);
0388         }
0389 
0390         if (!m_ui->fastUsername->text().isEmpty()) {
0391             setting.setIdentity(m_ui->fastUsername->text());
0392         }
0393 
0394         if (!m_ui->fastPassword->text().isEmpty()) {
0395             setting.setPassword(m_ui->fastPassword->text());
0396         }
0397 
0398         if (m_ui->fastPassword->passwordOption() == PasswordField::StoreForAllUsers) {
0399             setting.setPasswordFlags(NetworkManager::Setting::None);
0400         } else if (m_ui->fastPassword->passwordOption() == PasswordField::StoreForUser) {
0401             setting.setPasswordFlags(NetworkManager::Setting::AgentOwned);
0402         } else {
0403             setting.setPasswordFlags(NetworkManager::Setting::NotSaved);
0404         }
0405     } else if (method == NetworkManager::Security8021xSetting::EapMethodTtls) {
0406         if (!m_ui->ttlsAnonIdentity->text().isEmpty()) {
0407             setting.setAnonymousIdentity(m_ui->ttlsAnonIdentity->text());
0408         }
0409 
0410         if (!m_ui->ttlsDomain->text().isEmpty()) {
0411             setting.setDomainSuffixMatch(m_ui->ttlsDomain->text());
0412         }
0413 
0414         if (m_ui->ttlsCACert->url().isValid()) {
0415             setting.setCaCertificate(m_ui->ttlsCACert->url().toString().toUtf8().append('\0'));
0416         }
0417 
0418         const int innerAuth = m_ui->ttlsInnerAuth->currentIndex();
0419         if (innerAuth == 0) {
0420             setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodPap);
0421         } else if (innerAuth == 1) {
0422             setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodMschap);
0423         } else if (innerAuth == 2) {
0424             setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodMschapv2);
0425         } else if (innerAuth == 3) {
0426             setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodChap);
0427         }
0428 
0429         if (!m_ui->ttlsUsername->text().isEmpty()) {
0430             setting.setIdentity(m_ui->ttlsUsername->text());
0431         }
0432 
0433         if (!m_ui->ttlsPassword->text().isEmpty()) {
0434             setting.setPassword(m_ui->ttlsPassword->text());
0435         }
0436 
0437         if (m_ui->ttlsPassword->passwordOption() == PasswordField::StoreForAllUsers) {
0438             setting.setPasswordFlags(NetworkManager::Setting::None);
0439         } else if (m_ui->ttlsPassword->passwordOption() == PasswordField::StoreForUser) {
0440             setting.setPasswordFlags(NetworkManager::Setting::AgentOwned);
0441         } else {
0442             setting.setPasswordFlags(NetworkManager::Setting::NotSaved);
0443         }
0444     } else if (method == NetworkManager::Security8021xSetting::EapMethodPeap) {
0445         if (!m_ui->peapAnonIdentity->text().isEmpty()) {
0446             setting.setAnonymousIdentity(m_ui->peapAnonIdentity->text());
0447         }
0448 
0449         if (!m_ui->peapDomain->text().isEmpty()) {
0450             setting.setDomainSuffixMatch(m_ui->peapDomain->text());
0451         }
0452 
0453         if (m_ui->peapCACert->url().isValid()) {
0454             setting.setCaCertificate(m_ui->peapCACert->url().toString().toUtf8().append('\0'));
0455         }
0456 
0457         setting.setPhase1PeapVersion(static_cast<NetworkManager::Security8021xSetting::PeapVersion>(m_ui->peapVersion->currentIndex() - 1));
0458         const int innerAuth = m_ui->peapInnerAuth->currentIndex();
0459         if (innerAuth == 0) {
0460             setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodMschapv2);
0461         } else if (innerAuth == 1) {
0462             setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodMd5);
0463         } else if (innerAuth == 2) {
0464             setting.setPhase2AuthMethod(NetworkManager::Security8021xSetting::AuthMethodGtc);
0465         }
0466 
0467         if (!m_ui->peapUsername->text().isEmpty()) {
0468             setting.setIdentity(m_ui->peapUsername->text());
0469         }
0470 
0471         if (!m_ui->peapPassword->text().isEmpty()) {
0472             setting.setPassword(m_ui->peapPassword->text());
0473         }
0474 
0475         if (m_ui->peapPassword->passwordOption() == PasswordField::StoreForAllUsers) {
0476             setting.setPasswordFlags(NetworkManager::Setting::None);
0477         } else if (m_ui->peapPassword->passwordOption() == PasswordField::StoreForUser) {
0478             setting.setPasswordFlags(NetworkManager::Setting::AgentOwned);
0479         } else {
0480             setting.setPasswordFlags(NetworkManager::Setting::NotSaved);
0481         }
0482     }
0483 
0484     return setting.toMap();
0485 }
0486 
0487 void Security8021x::setPasswordOption(PasswordField::PasswordOption option)
0488 {
0489     m_ui->fastPassword->setPasswordOption(option);
0490     m_ui->leapPassword->setPasswordOption(option);
0491     m_ui->md5Password->setPasswordOption(option);
0492     m_ui->peapPassword->setPasswordOption(option);
0493     m_ui->pwdPassword->setPasswordOption(option);
0494     m_ui->tlsPrivateKeyPassword->setPasswordOption(option);
0495     m_ui->ttlsPassword->setPasswordOption(option);
0496 }
0497 
0498 void Security8021x::altSubjectMatchesButtonClicked()
0499 {
0500     QPointer<EditListDialog> editor = new EditListDialog(this);
0501     editor->setAttribute(Qt::WA_DeleteOnClose);
0502 
0503     editor->setItems(m_ui->leTlsSubjectMatch->text().remove(QLatin1Char(' ')).split(QLatin1Char(','), Qt::SkipEmptyParts));
0504     editor->setWindowTitle(i18n("Alternative Subject Matches"));
0505     editor->setToolTip(
0506         i18n("<qt>This entry must be one of:<ul><li>DNS: &lt;name or ip address&gt;</li><li>EMAIL: &lt;email&gt;</li><li>URI: &lt;uri, e.g. "
0507              "https://www.kde.org&gt;</li></ul></qt>"));
0508     editor->setValidator(altSubjectValidator);
0509 
0510     connect(editor.data(), &QDialog::accepted, [editor, this]() {
0511         m_ui->leTlsSubjectMatch->setText(editor->items().join(QLatin1String(", ")));
0512     });
0513     editor->setModal(true);
0514     editor->show();
0515 }
0516 
0517 void Security8021x::connectToServersButtonClicked()
0518 {
0519     QPointer<EditListDialog> editor = new EditListDialog(this);
0520     editor->setAttribute(Qt::WA_DeleteOnClose);
0521 
0522     editor->setItems(m_ui->leTlsConnectToServers->text().remove(QLatin1Char(' ')).split(QLatin1Char(','), Qt::SkipEmptyParts));
0523     editor->setWindowTitle(i18n("Connect to these servers only"));
0524     editor->setValidator(serversValidator);
0525 
0526     connect(editor.data(), &QDialog::accepted, [editor, this]() {
0527         m_ui->leTlsConnectToServers->setText(editor->items().join(QLatin1String(", ")));
0528     });
0529     editor->setModal(true);
0530     editor->show();
0531 }
0532 
0533 bool Security8021x::isValid() const
0534 {
0535     NetworkManager::Security8021xSetting::EapMethod method =
0536         static_cast<NetworkManager::Security8021xSetting::EapMethod>(m_ui->auth->itemData(m_ui->auth->currentIndex()).toInt());
0537 
0538     if (method == NetworkManager::Security8021xSetting::EapMethodMd5) {
0539         return !m_ui->md5UserName->text().isEmpty()
0540             && (!m_ui->md5Password->text().isEmpty() || m_ui->md5Password->passwordOption() == PasswordField::AlwaysAsk);
0541     } else if (method == NetworkManager::Security8021xSetting::EapMethodTls) {
0542         if (m_ui->tlsIdentity->text().isEmpty()) {
0543             return false;
0544         }
0545 
0546         if (!m_ui->tlsPrivateKey->url().isValid()) {
0547             return false;
0548         }
0549 
0550         if (m_ui->tlsPrivateKeyPassword->passwordOption() == PasswordField::AlwaysAsk) {
0551             return true;
0552         }
0553 
0554         if (m_ui->tlsPrivateKeyPassword->text().isEmpty()) {
0555             return false;
0556         }
0557 
0558         QCA::Initializer init;
0559         QCA::ConvertResult convRes;
0560 
0561         // Try if the private key is in pkcs12 format bundled with client certificate
0562         if (QCA::isSupported("pkcs12")) {
0563             QCA::KeyBundle keyBundle = QCA::KeyBundle::fromFile(m_ui->tlsPrivateKey->url().path(), m_ui->tlsPrivateKeyPassword->text().toUtf8(), &convRes);
0564             // We can return the result of decryption when we managed to import the private key
0565             if (convRes == QCA::ConvertGood) {
0566                 return keyBundle.privateKey().canDecrypt();
0567             }
0568         }
0569 
0570         // If the private key is not in pkcs12 format, we need client certificate to be set
0571         if (!m_ui->tlsUserCert->url().isValid()) {
0572             return false;
0573         }
0574 
0575         // Try if the private key is in PEM format and return the result of decryption if we managed to open it
0576         QCA::PrivateKey key = QCA::PrivateKey::fromPEMFile(m_ui->tlsPrivateKey->url().path(), m_ui->tlsPrivateKeyPassword->text().toUtf8(), &convRes);
0577         if (convRes == QCA::ConvertGood) {
0578             return key.canDecrypt();
0579         }
0580 
0581         // TODO Try other formats (DER - mainly used in Windows)
0582         // TODO Validate other certificates??
0583     } else if (method == NetworkManager::Security8021xSetting::EapMethodLeap) {
0584         return !m_ui->leapUsername->text().isEmpty()
0585             && (!m_ui->leapPassword->text().isEmpty() || m_ui->leapPassword->passwordOption() == PasswordField::AlwaysAsk);
0586     } else if (method == NetworkManager::Security8021xSetting::EapMethodPwd) {
0587         return !m_ui->pwdUsername->text().isEmpty()
0588             && (!m_ui->pwdPassword->text().isEmpty() || m_ui->pwdPassword->passwordOption() == PasswordField::AlwaysAsk);
0589     } else if (method == NetworkManager::Security8021xSetting::EapMethodFast) {
0590         if (!m_ui->fastAllowPacProvisioning->isChecked() && !m_ui->pacFile->url().isValid()) {
0591             return false;
0592         }
0593         return !m_ui->fastUsername->text().isEmpty()
0594             && (!m_ui->fastPassword->text().isEmpty() || m_ui->fastPassword->passwordOption() == PasswordField::AlwaysAsk);
0595     } else if (method == NetworkManager::Security8021xSetting::EapMethodTtls) {
0596         return !m_ui->ttlsUsername->text().isEmpty()
0597             && (!m_ui->ttlsPassword->text().isEmpty() || m_ui->ttlsPassword->passwordOption() == PasswordField::AlwaysAsk);
0598     } else if (method == NetworkManager::Security8021xSetting::EapMethodPeap) {
0599         return !m_ui->peapUsername->text().isEmpty()
0600             && (!m_ui->peapPassword->text().isEmpty() || m_ui->peapPassword->passwordOption() == PasswordField::AlwaysAsk);
0601     }
0602 
0603     return true;
0604 }
0605 
0606 void Security8021x::currentAuthChanged(int index)
0607 {
0608     Q_UNUSED(index);
0609     KAcceleratorManager::manage(m_ui->stackedWidget->currentWidget());
0610 }
0611 
0612 #include "moc_security802-1x.cpp"