File indexing completed on 2024-04-28 05:33:53
0001 /* 0002 SPDX-FileCopyrightText: 2013 Jan Grulich <jgrulich@redhat.com> 0003 SPDX-FileCopyrightText: 2013 Lukas Tinkl <ltinkl@redhat.com> 0004 SPDX-FileCopyrightText: 2013 Daniel Nicoletti <dantti12@gmail.com> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #include "secretagent.h" 0010 #include "passworddialog.h" 0011 0012 #include "plasma_nm_kded.h" 0013 0014 #include "configuration.h" 0015 0016 #include <NetworkManagerQt/ConnectionSettings> 0017 #include <NetworkManagerQt/GenericTypes> 0018 #include <NetworkManagerQt/GsmSetting> 0019 #include <NetworkManagerQt/Security8021xSetting> 0020 #include <NetworkManagerQt/Settings> 0021 #include <NetworkManagerQt/VpnSetting> 0022 #include <NetworkManagerQt/WireguardSetting> 0023 #include <NetworkManagerQt/WirelessSecuritySetting> 0024 #include <NetworkManagerQt/WirelessSetting> 0025 0026 #include <QDBusConnection> 0027 #include <QDialog> 0028 #include <QStringBuilder> 0029 0030 #include <KConfig> 0031 #include <KConfigGroup> 0032 #include <KLocalizedString> 0033 #include <KPluginFactory> 0034 #include <KWallet> 0035 #include <KWindowSystem> 0036 #include <KX11Extras> 0037 0038 SecretAgent::SecretAgent(QObject *parent) 0039 : NetworkManager::SecretAgent(QStringLiteral("org.kde.plasma.networkmanagement"), NetworkManager::SecretAgent::Capability::VpnHints, parent) 0040 , m_openWalletFailed(false) 0041 , m_wallet(nullptr) 0042 , m_dialog(nullptr) 0043 { 0044 connect(NetworkManager::notifier(), &NetworkManager::Notifier::serviceDisappeared, this, &SecretAgent::killDialogs); 0045 0046 // We have to import secrets previously stored in plaintext files 0047 importSecretsFromPlainTextFiles(); 0048 } 0049 0050 SecretAgent::~SecretAgent() = default; 0051 0052 NMVariantMapMap SecretAgent::GetSecrets(const NMVariantMapMap &connection, 0053 const QDBusObjectPath &connection_path, 0054 const QString &setting_name, 0055 const QStringList &hints, 0056 uint flags) 0057 { 0058 qCDebug(PLASMA_NM_KDED_LOG) << Q_FUNC_INFO; 0059 qCDebug(PLASMA_NM_KDED_LOG) << "Path:" << connection_path.path(); 0060 qCDebug(PLASMA_NM_KDED_LOG) << "Setting name:" << setting_name; 0061 qCDebug(PLASMA_NM_KDED_LOG) << "Hints:" << hints; 0062 qCDebug(PLASMA_NM_KDED_LOG) << "Flags:" << flags; 0063 0064 const QString callId = connection_path.path() % setting_name; 0065 for (const SecretsRequest &request : std::as_const(m_calls)) { 0066 if (request == callId) { 0067 qCWarning(PLASMA_NM_KDED_LOG) << "GetSecrets was called again! This should not happen, cancelling first call" << connection_path.path() 0068 << setting_name; 0069 CancelGetSecrets(connection_path, setting_name); 0070 break; 0071 } 0072 } 0073 0074 setDelayedReply(true); 0075 SecretsRequest request(SecretsRequest::GetSecrets); 0076 request.callId = callId; 0077 request.connection = connection; 0078 request.connection_path = connection_path; 0079 request.flags = static_cast<NetworkManager::SecretAgent::GetSecretsFlags>(flags); 0080 request.hints = hints; 0081 request.setting_name = setting_name; 0082 request.message = message(); 0083 m_calls << request; 0084 0085 processNext(); 0086 0087 return {}; 0088 } 0089 0090 void SecretAgent::SaveSecrets(const NMVariantMapMap &connection, const QDBusObjectPath &connection_path) 0091 { 0092 qCDebug(PLASMA_NM_KDED_LOG) << Q_FUNC_INFO; 0093 qCDebug(PLASMA_NM_KDED_LOG) << "Path:" << connection_path.path(); 0094 // qCDebug(PLASMA_NM_KDED_LOG) << "Setting:" << connection; 0095 0096 setDelayedReply(true); 0097 SecretsRequest::Type type; 0098 if (hasSecrets(connection)) { 0099 type = SecretsRequest::SaveSecrets; 0100 } else { 0101 type = SecretsRequest::DeleteSecrets; 0102 } 0103 SecretsRequest request(type); 0104 request.connection = connection; 0105 request.connection_path = connection_path; 0106 request.message = message(); 0107 m_calls << request; 0108 0109 processNext(); 0110 } 0111 0112 void SecretAgent::DeleteSecrets(const NMVariantMapMap &connection, const QDBusObjectPath &connection_path) 0113 { 0114 qCDebug(PLASMA_NM_KDED_LOG) << Q_FUNC_INFO; 0115 qCDebug(PLASMA_NM_KDED_LOG) << "Path:" << connection_path.path(); 0116 // qCDebug(PLASMA_NM_KDED_LOG) << "Setting:" << connection; 0117 0118 setDelayedReply(true); 0119 SecretsRequest request(SecretsRequest::DeleteSecrets); 0120 request.connection = connection; 0121 request.connection_path = connection_path; 0122 request.message = message(); 0123 m_calls << request; 0124 0125 processNext(); 0126 } 0127 0128 void SecretAgent::CancelGetSecrets(const QDBusObjectPath &connection_path, const QString &setting_name) 0129 { 0130 qCDebug(PLASMA_NM_KDED_LOG) << Q_FUNC_INFO; 0131 qCDebug(PLASMA_NM_KDED_LOG) << "Path:" << connection_path.path(); 0132 qCDebug(PLASMA_NM_KDED_LOG) << "Setting name:" << setting_name; 0133 0134 QString callId = connection_path.path() % setting_name; 0135 for (int i = 0; i < m_calls.size(); ++i) { 0136 SecretsRequest request = m_calls.at(i); 0137 if (request.type == SecretsRequest::GetSecrets && callId == request.callId) { 0138 if (m_dialog == request.dialog) { 0139 m_dialog = nullptr; 0140 } 0141 delete request.dialog; 0142 sendError(SecretAgent::AgentCanceled, QStringLiteral("Agent canceled the password dialog"), request.message); 0143 m_calls.removeAt(i); 0144 break; 0145 } 0146 } 0147 0148 processNext(); 0149 } 0150 0151 void SecretAgent::dialogAccepted() 0152 { 0153 for (int i = 0; i < m_calls.size(); ++i) { 0154 SecretsRequest request = m_calls[i]; 0155 if (request.type == SecretsRequest::GetSecrets && request.dialog == m_dialog) { 0156 NMStringMap tmpOpenconnectSecrets; 0157 NMVariantMapMap connection = request.dialog->secrets(); 0158 if (connection.contains(QStringLiteral("vpn"))) { 0159 if (connection.value(QStringLiteral("vpn")).contains(QStringLiteral("tmp-secrets"))) { 0160 QVariantMap vpnSetting = connection.value(QStringLiteral("vpn")); 0161 tmpOpenconnectSecrets = qdbus_cast<NMStringMap>(vpnSetting.take(QStringLiteral("tmp-secrets"))); 0162 connection.insert(QStringLiteral("vpn"), vpnSetting); 0163 } 0164 } 0165 0166 sendSecrets(connection, request.message); 0167 NetworkManager::ConnectionSettings::Ptr connectionSettings = 0168 NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(connection)); 0169 NetworkManager::ConnectionSettings::Ptr completeConnectionSettings; 0170 NetworkManager::Connection::Ptr con = NetworkManager::findConnectionByUuid(connectionSettings->uuid()); 0171 if (con) { 0172 completeConnectionSettings = con->settings(); 0173 } else { 0174 completeConnectionSettings = connectionSettings; 0175 } 0176 if (request.saveSecretsWithoutReply && completeConnectionSettings->connectionType() != NetworkManager::ConnectionSettings::Vpn) { 0177 bool requestOffline = true; 0178 if (completeConnectionSettings->connectionType() == NetworkManager::ConnectionSettings::Gsm) { 0179 NetworkManager::GsmSetting::Ptr gsmSetting = 0180 completeConnectionSettings->setting(NetworkManager::Setting::Gsm).staticCast<NetworkManager::GsmSetting>(); 0181 if (gsmSetting) { 0182 if (gsmSetting->passwordFlags().testFlag(NetworkManager::Setting::NotSaved) // 0183 || gsmSetting->passwordFlags().testFlag(NetworkManager::Setting::NotRequired)) { 0184 requestOffline = false; 0185 } else if (gsmSetting->pinFlags().testFlag(NetworkManager::Setting::NotSaved) // 0186 || gsmSetting->pinFlags().testFlag(NetworkManager::Setting::NotRequired)) { 0187 requestOffline = false; 0188 } 0189 } 0190 } else if (completeConnectionSettings->connectionType() == NetworkManager::ConnectionSettings::Wireless) { 0191 NetworkManager::WirelessSecuritySetting::Ptr wirelessSecuritySetting = 0192 completeConnectionSettings->setting(NetworkManager::Setting::WirelessSecurity).staticCast<NetworkManager::WirelessSecuritySetting>(); 0193 if (wirelessSecuritySetting 0194 && ((wirelessSecuritySetting->keyMgmt() == NetworkManager::WirelessSecuritySetting::WpaEap) 0195 || (wirelessSecuritySetting->keyMgmt() == NetworkManager::WirelessSecuritySetting::WpaEapSuiteB192))) { 0196 NetworkManager::Security8021xSetting::Ptr security8021xSetting = 0197 completeConnectionSettings->setting(NetworkManager::Setting::Security8021x).staticCast<NetworkManager::Security8021xSetting>(); 0198 if (security8021xSetting) { 0199 if (security8021xSetting->eapMethods().contains(NetworkManager::Security8021xSetting::EapMethodFast) // 0200 || security8021xSetting->eapMethods().contains(NetworkManager::Security8021xSetting::EapMethodTtls) // 0201 || security8021xSetting->eapMethods().contains(NetworkManager::Security8021xSetting::EapMethodPeap)) { 0202 if (security8021xSetting->passwordFlags().testFlag(NetworkManager::Setting::NotSaved) 0203 || security8021xSetting->passwordFlags().testFlag(NetworkManager::Setting::NotRequired)) { 0204 requestOffline = false; 0205 } 0206 } 0207 } 0208 } 0209 } 0210 0211 if (requestOffline) { 0212 SecretsRequest requestOffline(SecretsRequest::SaveSecrets); 0213 requestOffline.connection = connection; 0214 requestOffline.connection_path = request.connection_path; 0215 requestOffline.saveSecretsWithoutReply = true; 0216 m_calls << requestOffline; 0217 } 0218 } else if (request.saveSecretsWithoutReply && completeConnectionSettings->connectionType() == NetworkManager::ConnectionSettings::Vpn 0219 && !tmpOpenconnectSecrets.isEmpty()) { 0220 NetworkManager::VpnSetting::Ptr vpnSetting = 0221 completeConnectionSettings->setting(NetworkManager::Setting::Vpn).staticCast<NetworkManager::VpnSetting>(); 0222 if (vpnSetting) { 0223 NMStringMap data = vpnSetting->data(); 0224 NMStringMap secrets = vpnSetting->secrets(); 0225 0226 // Load secrets from auth dialog which are returned back to NM 0227 if (connection.value(QStringLiteral("vpn")).contains(QStringLiteral("secrets"))) { 0228 secrets.insert(qdbus_cast<NMStringMap>(connection.value(QStringLiteral("vpn")).value(QStringLiteral("secrets")))); 0229 } 0230 0231 // Load temporary secrets from auth dialog which are not returned to NM 0232 for (const QString &key : tmpOpenconnectSecrets.keys()) { 0233 if (secrets.contains(QStringLiteral("save_passwords")) && secrets.value(QStringLiteral("save_passwords")) == QLatin1String("yes")) { 0234 data.insert(key + QLatin1String("-flags"), QString::number(NetworkManager::Setting::AgentOwned)); 0235 } else { 0236 data.insert(key + QLatin1String("-flags"), QString::number(NetworkManager::Setting::NotSaved)); 0237 } 0238 secrets.insert(key, tmpOpenconnectSecrets.value(key)); 0239 } 0240 0241 vpnSetting->setData(data); 0242 vpnSetting->setSecrets(secrets); 0243 if (!con) { 0244 con = NetworkManager::findConnection(request.connection_path.path()); 0245 } 0246 0247 if (con) { 0248 con->update(completeConnectionSettings->toMap()); 0249 } 0250 } 0251 } 0252 0253 m_calls.removeAt(i); 0254 break; 0255 } 0256 } 0257 0258 m_dialog->deleteLater(); 0259 m_dialog = nullptr; 0260 0261 processNext(); 0262 } 0263 0264 void SecretAgent::dialogRejected() 0265 { 0266 for (int i = 0; i < m_calls.size(); ++i) { 0267 SecretsRequest request = m_calls[i]; 0268 if (request.type == SecretsRequest::GetSecrets && request.dialog == m_dialog) { 0269 sendError(SecretAgent::UserCanceled, QStringLiteral("User canceled the password dialog"), request.message); 0270 m_calls.removeAt(i); 0271 break; 0272 } 0273 } 0274 0275 m_dialog->deleteLater(); 0276 m_dialog = nullptr; 0277 0278 processNext(); 0279 } 0280 0281 void SecretAgent::killDialogs() 0282 { 0283 int i = 0; 0284 while (i < m_calls.size()) { 0285 SecretsRequest request = m_calls[i]; 0286 if (request.type == SecretsRequest::GetSecrets) { 0287 delete request.dialog; 0288 m_calls.removeAt(i); 0289 } 0290 0291 ++i; 0292 } 0293 } 0294 0295 void SecretAgent::walletOpened(bool success) 0296 { 0297 if (!success) { 0298 m_openWalletFailed = true; 0299 m_wallet->deleteLater(); 0300 m_wallet = nullptr; 0301 } else { 0302 m_openWalletFailed = false; 0303 } 0304 0305 processNext(); 0306 } 0307 0308 void SecretAgent::walletClosed() 0309 { 0310 if (m_wallet) { 0311 m_wallet->deleteLater(); 0312 } 0313 m_wallet = nullptr; 0314 } 0315 0316 void SecretAgent::processNext() 0317 { 0318 int i = 0; 0319 while (i < m_calls.size()) { 0320 SecretsRequest &request = m_calls[i]; 0321 switch (request.type) { 0322 case SecretsRequest::GetSecrets: 0323 if (processGetSecrets(request)) { 0324 m_calls.removeAt(i); 0325 continue; 0326 } 0327 break; 0328 case SecretsRequest::SaveSecrets: 0329 if (processSaveSecrets(request)) { 0330 m_calls.removeAt(i); 0331 continue; 0332 } 0333 break; 0334 case SecretsRequest::DeleteSecrets: 0335 if (processDeleteSecrets(request)) { 0336 m_calls.removeAt(i); 0337 continue; 0338 } 0339 break; 0340 } 0341 ++i; 0342 } 0343 } 0344 0345 bool SecretAgent::processGetSecrets(SecretsRequest &request) const 0346 { 0347 if (m_dialog) { 0348 return false; 0349 } 0350 0351 NetworkManager::ConnectionSettings::Ptr connectionSettings = 0352 NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(request.connection)); 0353 NetworkManager::Setting::Ptr setting = connectionSettings->setting(request.setting_name); 0354 0355 const bool requestNew = request.flags & RequestNew; 0356 const bool userRequested = request.flags & UserRequested; 0357 const bool allowInteraction = request.flags & AllowInteraction; 0358 const bool isVpn = (setting->type() == NetworkManager::Setting::Vpn); 0359 const bool isWireGuard = (setting->type() == NetworkManager::Setting::WireGuard); 0360 0361 if (isVpn) { 0362 NetworkManager::VpnSetting::Ptr vpnSetting = connectionSettings->setting(NetworkManager::Setting::Vpn).dynamicCast<NetworkManager::VpnSetting>(); 0363 if (vpnSetting->serviceType() == QLatin1String("org.freedesktop.NetworkManager.ssh") && vpnSetting->data()["auth-type"] == QLatin1String("ssh-agent")) { 0364 QString authSock = qgetenv("SSH_AUTH_SOCK"); 0365 qCDebug(PLASMA_NM_KDED_LOG) << Q_FUNC_INFO << "Sending SSH auth socket" << authSock; 0366 0367 if (authSock.isEmpty()) { 0368 sendError(SecretAgent::NoSecrets, QStringLiteral("SSH_AUTH_SOCK not present"), request.message); 0369 } else { 0370 NMStringMap secrets; 0371 secrets.insert(QStringLiteral("ssh-auth-sock"), authSock); 0372 0373 QVariantMap secretData; 0374 secretData.insert(QStringLiteral("secrets"), QVariant::fromValue<NMStringMap>(secrets)); 0375 request.connection[request.setting_name] = secretData; 0376 sendSecrets(request.connection, request.message); 0377 } 0378 return true; 0379 } 0380 } 0381 0382 NMStringMap secretsMap; 0383 if (!requestNew && useWallet()) { 0384 if (m_wallet->isOpen()) { 0385 if (m_wallet->hasFolder(QStringLiteral("Network Management")) && m_wallet->setFolder(QStringLiteral("Network Management"))) { 0386 QString key = QLatin1Char('{') % connectionSettings->uuid() % QLatin1Char('}') % QLatin1Char(';') % request.setting_name; 0387 m_wallet->readMap(key, secretsMap); 0388 } 0389 } else { 0390 qCDebug(PLASMA_NM_KDED_LOG) << Q_FUNC_INFO << "Waiting for the wallet to open"; 0391 return false; 0392 } 0393 } 0394 0395 if (!secretsMap.isEmpty()) { 0396 setting->secretsFromStringMap(secretsMap); 0397 if (!(isVpn || isWireGuard) && setting->needSecrets(requestNew).isEmpty()) { 0398 // Enough secrets were retrieved from storage 0399 request.connection[request.setting_name] = setting->secretsToMap(); 0400 sendSecrets(request.connection, request.message); 0401 return true; 0402 } 0403 } 0404 0405 if (!Configuration::self().showPasswordDialog()) { 0406 sendError(SecretAgent::NoSecrets, QStringLiteral("Cannot authenticate"), request.message); 0407 Q_EMIT secretsError(request.connection_path.path(), 0408 i18n("Authentication to %1 failed. Wrong password?", request.connection.value("connection").value("id").toString())); 0409 return true; 0410 } else if (isWireGuard && userRequested) { // Just return what we have 0411 NMVariantMapMap result; 0412 NetworkManager::WireGuardSetting::Ptr wireGuardSetting; 0413 wireGuardSetting = connectionSettings->setting(NetworkManager::Setting::WireGuard).dynamicCast<NetworkManager::WireGuardSetting>(); 0414 // FIXME workaround when NM is asking for secrets which should be system-stored, if we send an empty map it 0415 // won't ask for additional secrets with AllowInteraction flag which would display the authentication dialog 0416 if (wireGuardSetting->secretsToMap().isEmpty()) { 0417 // Insert an empty secrets map as it was before I fixed it in NetworkManagerQt to make sure NM will ask again 0418 // with flags we need 0419 QVariantMap secretsMap; 0420 secretsMap.insert(QStringLiteral("secrets"), QVariant::fromValue<NMStringMap>(NMStringMap())); 0421 result.insert(QStringLiteral("wireguard"), secretsMap); 0422 } else { 0423 result.insert(QStringLiteral("wireguard"), wireGuardSetting->secretsToMap()); 0424 } 0425 sendSecrets(result, request.message); 0426 return true; 0427 } else if (requestNew || (allowInteraction && !setting->needSecrets(requestNew).isEmpty()) || (allowInteraction && userRequested) 0428 || (isVpn && allowInteraction)) { 0429 m_dialog = new PasswordDialog(connectionSettings, request.flags, request.setting_name, request.hints); 0430 connect(m_dialog, &PasswordDialog::accepted, this, &SecretAgent::dialogAccepted); 0431 connect(m_dialog, &PasswordDialog::rejected, this, &SecretAgent::dialogRejected); 0432 0433 if (m_dialog->hasError()) { 0434 sendError(m_dialog->error(), m_dialog->errorMessage(), request.message); 0435 delete m_dialog; 0436 m_dialog = nullptr; 0437 return true; 0438 } else { 0439 request.dialog = m_dialog; 0440 request.saveSecretsWithoutReply = !connectionSettings->permissions().isEmpty(); 0441 m_dialog->show(); 0442 if (KWindowSystem::isPlatformX11()) { 0443 KX11Extras::setState(m_dialog->winId(), NET::KeepAbove); 0444 } 0445 return false; 0446 } 0447 } else if (isVpn && userRequested) { // just return what we have 0448 NMVariantMapMap result; 0449 NetworkManager::VpnSetting::Ptr vpnSetting; 0450 vpnSetting = connectionSettings->setting(NetworkManager::Setting::Vpn).dynamicCast<NetworkManager::VpnSetting>(); 0451 // FIXME workaround when NM is asking for secrets which should be system-stored, if we send an empty map it 0452 // won't ask for additional secrets with AllowInteraction flag which would display the authentication dialog 0453 if (vpnSetting->secretsToMap().isEmpty()) { 0454 // Insert an empty secrets map as it was before I fixed it in NetworkManagerQt to make sure NM will ask again 0455 // with flags we need 0456 QVariantMap secretsMap; 0457 secretsMap.insert(QStringLiteral("secrets"), QVariant::fromValue<NMStringMap>(NMStringMap())); 0458 result.insert(QStringLiteral("vpn"), secretsMap); 0459 } else { 0460 result.insert(QStringLiteral("vpn"), vpnSetting->secretsToMap()); 0461 } 0462 sendSecrets(result, request.message); 0463 return true; 0464 } else if (setting->needSecrets().isEmpty()) { 0465 NMVariantMapMap result; 0466 result.insert(setting->name(), setting->secretsToMap()); 0467 sendSecrets(result, request.message); 0468 return true; 0469 } else { 0470 sendError(SecretAgent::InternalError, QStringLiteral("Plasma-nm did not know how to handle the request"), request.message); 0471 return true; 0472 } 0473 } 0474 0475 bool SecretAgent::processSaveSecrets(SecretsRequest &request) const 0476 { 0477 if (useWallet()) { 0478 if (m_wallet->isOpen()) { 0479 NetworkManager::ConnectionSettings connectionSettings(request.connection); 0480 0481 if (!m_wallet->hasFolder(QStringLiteral("Network Management"))) { 0482 m_wallet->createFolder(QStringLiteral("Network Management")); 0483 } 0484 0485 if (m_wallet->setFolder(QStringLiteral("Network Management"))) { 0486 for (const NetworkManager::Setting::Ptr &setting : connectionSettings.settings()) { 0487 NMStringMap secretsMap = setting->secretsToStringMap(); 0488 0489 if (!secretsMap.isEmpty()) { 0490 QString entryName = QLatin1Char('{') % connectionSettings.uuid() % QLatin1Char('}') % QLatin1Char(';') % setting->name(); 0491 m_wallet->writeMap(entryName, secretsMap); 0492 } 0493 } 0494 } else if (!request.saveSecretsWithoutReply) { 0495 sendError(SecretAgent::InternalError, QStringLiteral("Could not store secrets in the wallet."), request.message); 0496 return true; 0497 } 0498 } else { 0499 qCDebug(PLASMA_NM_KDED_LOG) << Q_FUNC_INFO << "Waiting for the wallet to open"; 0500 return false; 0501 } 0502 } 0503 0504 if (!request.saveSecretsWithoutReply) { 0505 QDBusMessage reply = request.message.createReply(); 0506 if (!QDBusConnection::systemBus().send(reply)) { 0507 qCWarning(PLASMA_NM_KDED_LOG) << "Failed put save secrets reply into the queue"; 0508 } 0509 } 0510 0511 return true; 0512 } 0513 0514 bool SecretAgent::processDeleteSecrets(SecretsRequest &request) const 0515 { 0516 if (useWallet()) { 0517 if (m_wallet->isOpen()) { 0518 if (m_wallet->hasFolder(QStringLiteral("Network Management")) && m_wallet->setFolder(QStringLiteral("Network Management"))) { 0519 NetworkManager::ConnectionSettings connectionSettings(request.connection); 0520 for (const NetworkManager::Setting::Ptr &setting : connectionSettings.settings()) { 0521 QString entryName = QLatin1Char('{') % connectionSettings.uuid() % QLatin1Char('}') % QLatin1Char(';') % setting->name(); 0522 for (const QString &entry : m_wallet->entryList()) { 0523 if (entry.startsWith(entryName)) { 0524 m_wallet->removeEntry(entryName); 0525 } 0526 } 0527 } 0528 } 0529 } else { 0530 qCDebug(PLASMA_NM_KDED_LOG) << Q_FUNC_INFO << "Waiting for the wallet to open"; 0531 return false; 0532 } 0533 } 0534 0535 QDBusMessage reply = request.message.createReply(); 0536 if (!QDBusConnection::systemBus().send(reply)) { 0537 qCWarning(PLASMA_NM_KDED_LOG) << "Failed put delete secrets reply into the queue"; 0538 } 0539 0540 return true; 0541 } 0542 0543 bool SecretAgent::useWallet() const 0544 { 0545 if (m_wallet) { 0546 return true; 0547 } 0548 0549 /* If opening of KWallet failed before, we should not try to open it again and 0550 * we should return false instead */ 0551 if (m_openWalletFailed) { 0552 m_openWalletFailed = false; 0553 return false; 0554 } 0555 0556 if (KWallet::Wallet::isEnabled()) { 0557 m_wallet = KWallet::Wallet::openWallet(KWallet::Wallet::LocalWallet(), 0, KWallet::Wallet::Asynchronous); 0558 if (m_wallet) { 0559 connect(m_wallet, &KWallet::Wallet::walletOpened, this, &SecretAgent::walletOpened); 0560 connect(m_wallet, &KWallet::Wallet::walletClosed, this, &SecretAgent::walletClosed); 0561 return true; 0562 } else { 0563 qCWarning(PLASMA_NM_KDED_LOG) << "Error opening kwallet."; 0564 } 0565 } else if (m_wallet) { 0566 m_wallet->deleteLater(); 0567 m_wallet = nullptr; 0568 } 0569 0570 return false; 0571 } 0572 0573 bool SecretAgent::hasSecrets(const NMVariantMapMap &connection) const 0574 { 0575 NetworkManager::ConnectionSettings connectionSettings(connection); 0576 for (const NetworkManager::Setting::Ptr &setting : connectionSettings.settings()) { 0577 if (!setting->secretsToMap().isEmpty()) { 0578 return true; 0579 } 0580 } 0581 0582 return false; 0583 } 0584 0585 void SecretAgent::sendSecrets(const NMVariantMapMap &secrets, const QDBusMessage &message) const 0586 { 0587 QDBusMessage reply; 0588 reply = message.createReply(QVariant::fromValue(secrets)); 0589 if (!QDBusConnection::systemBus().send(reply)) { 0590 qCWarning(PLASMA_NM_KDED_LOG) << "Failed put the secret into the queue"; 0591 } 0592 } 0593 0594 void SecretAgent::importSecretsFromPlainTextFiles() 0595 { 0596 KConfig config(QStringLiteral("plasma-networkmanagement"), KConfig::SimpleConfig); 0597 0598 // No action is required when the list of secrets is empty 0599 if (!config.groupList().isEmpty()) { 0600 for (const QString &groupName : config.groupList()) { 0601 QString loadedUuid = groupName.split(QLatin1Char(';')).first().remove('{').remove('}'); 0602 QString loadedSettingType = groupName.split(QLatin1Char(';')).last(); 0603 NetworkManager::Connection::Ptr connection = NetworkManager::findConnectionByUuid(loadedUuid); 0604 if (connection) { 0605 NetworkManager::Setting::SecretFlags secretFlags = 0606 KWallet::Wallet::isEnabled() ? NetworkManager::Setting::AgentOwned : NetworkManager::Setting::None; 0607 QMap<QString, QString> secrets = config.entryMap(groupName); 0608 NMVariantMapMap settings = connection->settings()->toMap(); 0609 0610 for (const QString &setting : settings.keys()) { 0611 if (setting == QLatin1String("vpn")) { 0612 NetworkManager::VpnSetting::Ptr vpnSetting = 0613 connection->settings()->setting(NetworkManager::Setting::Vpn).staticCast<NetworkManager::VpnSetting>(); 0614 if (vpnSetting) { 0615 // Add loaded secrets from the config file 0616 vpnSetting->secretsFromStringMap(secrets); 0617 0618 NMStringMap vpnData = vpnSetting->data(); 0619 // Reset flags, we can't save secrets to our secret agent when KWallet is not enabled, because 0620 // we dropped support for plaintext files, therefore they need to be stored to NetworkManager 0621 for (const QString &key : vpnData.keys()) { 0622 if (key.endsWith(QLatin1String("-flags"))) { 0623 vpnData.insert(key, QString::number((int)secretFlags)); 0624 } 0625 } 0626 0627 vpnSetting->setData(vpnData); 0628 settings.insert(setting, vpnSetting->toMap()); 0629 connection->update(settings); 0630 } 0631 } else { 0632 if (setting == loadedSettingType) { 0633 QVariantMap tmpSetting = settings.value(setting); 0634 // Reset flags, we can't save secrets to our secret agent when KWallet is not enabled, because 0635 // we dropped support for plaintext files, therefore they need to be stored to NetworkManager 0636 for (const QString &key : tmpSetting.keys()) { 0637 if (key.endsWith(QLatin1String("-flags"))) { 0638 tmpSetting.insert(key, (int)secretFlags); 0639 } 0640 } 0641 0642 // Add loaded secrets from the config file 0643 QMap<QString, QString>::const_iterator it = secrets.constBegin(); 0644 QMap<QString, QString>::const_iterator end = secrets.constEnd(); 0645 for (; it != end; ++it) { 0646 tmpSetting.insert(it.key(), it.value()); 0647 } 0648 0649 // Replace the old setting with the new one 0650 settings.insert(setting, tmpSetting); 0651 // Update the connection which re-saves secrets 0652 connection->update(settings); 0653 } 0654 } 0655 } 0656 } 0657 0658 // Remove the group 0659 KConfigGroup group(&config, groupName); 0660 group.deleteGroup(); 0661 } 0662 } 0663 } 0664 0665 #include "moc_secretagent.cpp"