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