10#include "kwalletd_debug.h"
12#include "kbetterthankdialog.h"
13#include "kwalletfreedesktopcollection.h"
14#include "kwalletfreedesktopitem.h"
15#include "kwalletfreedesktopprompt.h"
16#include "kwalletfreedesktopservice.h"
17#include "kwalletfreedesktopsession.h"
18#include "kwalletportalsecrets.h"
19#include "kwalletwizard.h"
22#include "knewwalletdialog.h"
25#include <KColorScheme>
27#include <KConfigGroup>
29#include <KLocalizedString>
31#include <KNewPasswordDialog>
32#include <KNotification>
33#include <KPasswordDialog>
34#include <KPluginFactory>
35#include <KSharedConfig>
36#include <kwalletentry.h>
37#include <kwindowsystem.h>
39#include <config-kwalletd.h>
45#include <gpgme++/key.h>
48#include <QApplication>
55#include "kwalletadaptor.h"
57static void startManagerForKwalletd()
60 QProcess::startDetached(QStringLiteral(
"kstart"), {QStringLiteral(
"kwalletmanager5"), QStringLiteral(
"--"), QStringLiteral(
"--kwalletd")});
62 QProcess::startDetached(QStringLiteral(
"kstart"), {QStringLiteral(
"kwalletmanager5"), QStringLiteral(
"--"), QStringLiteral(
"--kwalletd")});
68class KWalletTransaction
72 : tId(nextTransactionId)
79 if (nextTransactionId < 0) {
80 nextTransactionId = 0;
84 static int getTransactionId()
86 return nextTransactionId;
100 Type tType = Unknown;
105 bool cancelled =
false;
114 static int nextTransactionId;
117int KWalletTransaction::nextTransactionId = 0;
130 srand(time(
nullptr));
131 _showingFailureNotify =
false;
134 connect(&_closeTimers, &KTimeout::timedOut,
this, &KWalletD::timedOutClose);
135 connect(&_syncTimers, &KTimeout::timedOut,
this, &KWalletD::timedOutSync);
137 KConfig kwalletrc(QStringLiteral(
"kwalletrc"));
139 KConfigGroup cfgSecrets(&kwalletrc,
"org.freedesktop.secrets");
141 if (cfgWallet.readEntry<
bool>(
"apiEnabled",
true)) {
142 (void)
new KWalletAdaptor(
this);
151 new KWalletPortalSecrets(
this);
161 _dw->setObjectName(QStringLiteral(
"KWallet Directory Watcher"));
163 _dw->addDir(KWallet::Backend::getSaveLocation());
165 _dw->startScan(
true);
172 if (cfgSecrets.readEntry<
bool>(
"apiEnabled",
true)) {
173 _fdoService.reset(
new KWalletFreedesktopService(
this));
184 qDeleteAll(_transactions);
189 return KWallet::Backend::encodeWalletName(name);
194 return KWallet::Backend::decodeWalletName(mangledName);
198void KWalletD::connectToScreenSaver()
200 screensaver =
new QDBusInterface(
"org.freedesktop.ScreenSaver",
"/ScreenSaver",
"org.freedesktop.ScreenSaver");
201 if (!screensaver->isValid()) {
202 qCDebug(KWALLETD_LOG) <<
"Service org.freedesktop.ScreenSaver not found. Retrying in 10 seconds...";
206 connect(screensaver, SIGNAL(ActiveChanged(
bool)), SLOT(screenSaverChanged(
bool)));
207 qCDebug(KWALLETD_LOG) <<
"connected to screen saver service.";
212int KWalletD::generateHandle()
219 }
while (_wallets.
contains(rc) || rc == 0);
224QPair<int, KWallet::Backend *> KWalletD::findWallet(
const QString &walletName)
const
226 Wallets::const_iterator it = _wallets.
constBegin();
227 const Wallets::const_iterator
end = _wallets.
constEnd();
228 for (; it !=
end; ++it) {
229 if (it.value()->walletName() == walletName) {
230 return qMakePair(it.key(), it.value());
233 return qMakePair(-1,
static_cast<KWallet::Backend *
>(
nullptr));
236bool KWalletD::_processing =
false;
238void KWalletD::processTransactions()
247 while (!_transactions.
isEmpty()) {
251 assert(_curtrans->tType != KWalletTransaction::Unknown);
253 switch (_curtrans->tType) {
254 case KWalletTransaction::Open:
255 res = doTransactionOpen(_curtrans->appid, _curtrans->wallet, _curtrans->isPath, _curtrans->wId, _curtrans->modal, _curtrans->service);
262 for (it = _transactions.
begin(); it != _transactions.
end(); ++it) {
263 KWalletTransaction *x = *it;
264 if (_curtrans->appid == x->appid && x->tType == KWalletTransaction::Open && x->wallet == _curtrans->wallet && x->wId == _curtrans->wId) {
265 x->tType = KWalletTransaction::OpenFail;
268 }
else if (_curtrans->cancelled) {
271 KWalletTransaction *_xact =
new KWalletTransaction(_curtrans->connection);
272 _xact->tType = KWalletTransaction::CloseCancelled;
273 _xact->appid = _curtrans->appid;
274 _xact->wallet = _curtrans->wallet;
275 _xact->service = _curtrans->service;
276 _transactions.
append(_xact);
280 _curtrans->res = res;
281 Q_EMIT walletAsyncOpened(_curtrans->tId, res);
284 case KWalletTransaction::OpenFail:
287 Q_EMIT walletAsyncOpened(_curtrans->tId, -1);
290 case KWalletTransaction::ChangePassword:
291 doTransactionChangePassword(_curtrans->appid, _curtrans->wallet, _curtrans->wId);
294 case KWalletTransaction::CloseCancelled:
295 doTransactionOpenCancelled(_curtrans->appid, _curtrans->wallet, _curtrans->service);
298 case KWalletTransaction::Unknown:
308 reply << _curtrans->res;
309 _curtrans->connection.
send(reply);
320int KWalletD::openPath(
const QString &path, qlonglong wId,
const QString &appid)
322 int tId = openPathAsync(path, wId, appid,
false);
335int KWalletD::open(
const QString &wallet, qlonglong wId,
const QString &appid)
341 KWalletTransaction *xact =
new KWalletTransaction(
connection());
342 _transactions.
append(xact);
348 xact->wallet = wallet;
351 xact->tType = KWalletTransaction::Open;
352 xact->isPath =
false;
361int KWalletD::nextTransactionId()
const
363 return KWalletTransaction::getTransactionId();
366int KWalletD::openAsync(
const QString &wallet,
377 KWalletTransaction *xact =
new KWalletTransaction(
connection);
378 _transactions.
append(xact);
381 xact->wallet = wallet;
384 xact->tType = KWalletTransaction::Open;
385 xact->isPath =
false;
398int KWalletD::openAsync(
const QString &wallet, qlonglong wId,
const QString &appid,
bool handleSession)
403int KWalletD::openPathAsync(
const QString &path, qlonglong wId,
const QString &appid,
bool handleSession)
409 KWalletTransaction *xact =
new KWalletTransaction(
connection());
410 _transactions.
append(xact);
416 xact->tType = KWalletTransaction::Open;
431void KWalletD::setupDialog(
QWidget *dialog, WId wId,
const QString &appid,
bool modal)
439 qWarning() <<
"Using kwallet without parent window!";
441 qWarning() <<
"Application '" << appid <<
"' using kwallet without parent window!";
459 activeDialog = dialog;
473void KWalletD::checkActiveDialog()
482 activeDialog->show();
486 WId
window = activeDialog->winId();
494int KWalletD::doTransactionOpen(
const QString &appid,
const QString &wallet,
bool isPath, qlonglong wId,
bool modal,
const QString &service)
496 if (_firstUse && !isPath) {
500 KConfig kwalletrc(QStringLiteral(
"kwalletrc"));
502 cfg.writeEntry(
"Default Wallet", wallet);
505 KConfig kwalletrc(QStringLiteral(
"kwalletrc"));
508 cfg.writeEntry(
"First Use",
false);
568 int rc = internalOpen(appid, wallet, isPath, WId(wId), modal, service);
572int KWalletD::internalOpen(
const QString &appid,
const QString &wallet,
bool isPath, WId w,
bool modal,
const QString &service)
574 bool brandNew =
false;
578 thisApp = QStringLiteral(
"KDE System");
583 if (implicitDeny(wallet, thisApp)) {
587 QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
588 int rc = walletInfo.first;
590 if (_wallets.
count() > 20) {
591 qCDebug(KWALLETD_LOG) <<
"Too many wallets open.";
595 KWallet::Backend *b =
new KWallet::Backend(wallet, isPath);
597 bool emptyPass =
false;
598 if ((isPath &&
QFile::exists(wallet)) || (!isPath && KWallet::Backend::exists(wallet))) {
603 assert(b->cipherType() != KWallet::BACKEND_CIPHER_UNKNOWN);
604 if (b->cipherType() == KWallet::BACKEND_CIPHER_GPG) {
616 if (0 != pwless || !b->isOpen()) {
620 b =
new KWallet::Backend(wallet, isPath);
624 kpd->
setPrompt(
i18n(
"<qt>KDE has requested to open the wallet '<b>%1</b>'. Please enter the password for this wallet below.</qt>",
628 i18n(
"<qt>The application '<b>%1</b>' has requested to open the wallet '<b>%2</b>'. Please enter the password for this wallet "
655 actionText =
i18nc(
"Text of a button for switching to the (unnamed) application requesting a password",
"Switch there");
659 i18nc(
"Text of a button for switching to the application requesting a password",
"Switch to %1", appid.
toHtmlEscaped());
668 while (!b->isOpen()) {
669 setupDialog(kpd, w, appid, modal);
672 int rc = b->open(password.
toUtf8());
674 const auto errorStr = KWallet::Backend::openRCToString(rc);
675 qCWarning(KWALLETD_LOG) <<
"Failed to open wallet" << wallet << errorStr;
676 kpd->
setPrompt(
i18n(
"<qt>Error opening the wallet '<b>%1</b>'. Please try again.<br />(Error code %2: %3)</qt>",
697 KWallet::BackendCipherType newWalletType = KWallet::BACKEND_CIPHER_UNKNOWN;
699 std::shared_ptr<KWallet::KNewWalletDialog> newWalletDlg(
new KWallet::KNewWalletDialog(appid, wallet,
QWidget::find(w)));
701 setupDialog(newWalletDlg.get(), (WId)w, appid,
true);
703 newWalletType = newWalletDlg->isBlowfish() ? KWallet::BACKEND_CIPHER_BLOWFISH : KWallet::BACKEND_CIPHER_GPG;
704 gpgKey = newWalletDlg->gpgKey();
711 if (newWalletType == KWallet::BACKEND_CIPHER_GPG) {
712 b->setCipherType(newWalletType);
714 }
else if (newWalletType == KWallet::BACKEND_CIPHER_BLOWFISH) {
716 b->setCipherType(KWallet::BACKEND_CIPHER_BLOWFISH);
724 i18n(
"KDE has requested to open the wallet. This is used to store sensitive data in a "
725 "secure fashion. Please enter a password to use with this wallet or click cancel to "
726 "deny the application's request."));
729 i18n(
"<qt>The application '<b>%1</b>' has requested to open the KDE wallet. This is "
730 "used to store sensitive data in a secure fashion. Please enter a password to use "
731 "with this wallet or click cancel to deny the application's request.</qt>",
735 if (appid.
length() == 0) {
737 i18n(
"<qt>KDE has requested to create a new wallet named '<b>%1</b>'. Please choose a "
738 "password for this wallet, or cancel to deny the application's request.</qt>",
742 i18n(
"<qt>The application '<b>%1</b>' has requested to create a new wallet named '<b>%2</b>'. "
743 "Please choose a password for this wallet, or cancel to deny the application's request.</qt>",
752 while (!b->isOpen()) {
753 setupDialog(kpd, w, appid, modal);
756 int rc = b->open(password.
toUtf8());
758 kpd->
setPrompt(
i18n(
"<qt>Error opening the wallet '<b>%1</b>'. Please try again.<br />(Error code %2: %3)</qt>",
761 KWallet::Backend::openRCToString(rc)));
773 if ((b->cipherType() == KWallet::BACKEND_CIPHER_BLOWFISH) && !emptyPass && (password.
isNull() || !b->isOpen())) {
778 if (emptyPass && !isAuthorizedApp(appid, wallet, w)) {
783 _wallets.
insert(rc = generateHandle(), b);
784 _sessions.addSession(appid, service, rc);
785 _syncTimers.addTimer(rc, _syncTime);
794 _closeTimers.addTimer(rc, _idleTime);
797 Q_EMIT walletCreated(wallet);
799 Q_EMIT walletOpened(wallet);
800 if (_wallets.
count() == 1 && _launchManager) {
801 startManagerForKwalletd();
807 walletInfo.second->ref();
808 bool isAuthorized = _sessions.hasSession(appid, rc) || isAuthorizedApp(appid, wallet, w);
812 walletInfo = findWallet(wallet);
814 if (walletInfo.first != -1) {
815 walletInfo.second->deref();
817 internalClose(walletInfo.second, walletInfo.first,
false);
821 if (walletInfo.first != -1) {
822 _sessions.addSession(appid, service, rc);
833bool KWalletD::isAuthorizedApp(
const QString &appid,
const QString &wallet, WId w)
843 thisApp = QStringLiteral(
"KDE System");
848 if (!implicitAllow(wallet, thisApp)) {
851 KBetterThanKDialog *dialog =
new KBetterThanKDialog;
854 dialog->setLabel(
i18n(
"<qt>KDE has requested access to the open wallet '<b>%1</b>'.</qt>", wallet.
toHtmlEscaped()));
856 dialog->setLabel(
i18n(
"<qt>The application '<b>%1</b>' has requested access to the open wallet '<b>%2</b>'.</qt>",
860 setupDialog(dialog, w, appid,
false);
861 response = dialog->
exec();
866 if (response == 0 || response == 1) {
875 _implicitAllowMap[wallet] += thisApp;
880 }
else if (response == 3) {
885 _implicitDenyMap[wallet] += thisApp;
896int KWalletD::deleteWallet(
const QString &wallet)
899 QString path = KWallet::Backend::getSaveLocation() +
"/" + encodeWalletName(wallet) +
".kwl";
900 QString pathSalt = KWallet::Backend::getSaveLocation() +
"/" + encodeWalletName(wallet) +
".salt";
903 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
904 internalClose(walletInfo.second, walletInfo.first,
true);
906 Q_EMIT walletDeleted(wallet);
924void KWalletD::changePassword(
const QString &wallet, qlonglong wId,
const QString &appid)
926 KWalletTransaction *xact =
new KWalletTransaction(
connection());
934 xact->wallet = wallet;
937 xact->tType = KWalletTransaction::ChangePassword;
939 _transactions.
append(xact);
946void KWalletD::initiateSync(
int handle)
949 _syncTimers.addTimer(handle, _syncTime);
950 _syncTimers.resetTimer(handle, _syncTime);
953void KWalletD::doTransactionChangePassword(
const QString &appid,
const QString &wallet, qlonglong wId)
955 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
956 int handle = walletInfo.first;
957 KWallet::Backend *w = walletInfo.second;
959 bool reclose =
false;
961 handle = doTransactionOpen(appid, wallet,
false, wId,
false,
QLatin1String(
""));
964 i18n(
"Unable to open wallet. The wallet must be opened in order to change the password."),
965 i18n(
"KDE Wallet Service"));
969 w = _wallets.
value(handle);
976 if (w->cipherType() == KWallet::BACKEND_CIPHER_GPG) {
977 QString keyID = w->gpgKey().shortKeyID();
980 i18n(
"<qt>The <b>%1</b> wallet is encrypted using GPG key <b>%2</b>. Please use <b>GPG</b> tools (such "
981 "as <b>kleopatra</b>) to change the passphrase associated to that key.</qt>",
987 kpd->setPrompt(
i18n(
"<qt>Please choose a new password for the wallet '<b>%1</b>'.</qt>", wallet.
toHtmlEscaped()));
988 kpd->setWindowTitle(
i18n(
"KDE Wallet Service"));
989 kpd->setAllowEmptyPasswords(
true);
992 setupDialog(kpd, (WId)wId, appid,
false);
996 w->setPassword(p.
toUtf8());
997 int rc = w->close(
true);
1002 rc = w->open(p.
toUtf8());
1017 internalClose(w, handle,
true);
1021int KWalletD::close(
const QString &wallet,
bool force)
1023 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1024 int handle = walletInfo.first;
1025 KWallet::Backend *w = walletInfo.second;
1027 return internalClose(w, handle, force);
1030int KWalletD::internalClose(KWallet::Backend *
const w,
const int handle,
const bool force,
const bool saveBeforeClose)
1033 const QString &wallet = w->walletName();
1034 if ((w->refCount() == 0 && !_leaveOpen) || force) {
1036 _sessions.removeAllSessions(handle);
1038 _closeTimers.removeTimer(handle);
1040 _syncTimers.removeTimer(handle);
1042 w->close(saveBeforeClose);
1043 doCloseSignals(handle, wallet);
1053int KWalletD::close(
int handle,
bool force,
const QString &appid,
const QDBusMessage &message)
1055 KWallet::Backend *w = _wallets.
value(handle);
1058 if (_sessions.hasSession(appid, handle)) {
1060 bool removed = _sessions.removeSession(appid,
message.
service(), handle);
1062 if (removed || _sessions.removeSession(appid,
QLatin1String(
""), handle)) {
1065 return internalClose(w, handle, force);
1072int KWalletD::close(
int handle,
bool force,
const QString &appid)
1074 return close(handle, force, appid,
message());
1077bool KWalletD::isOpen(
const QString &wallet)
1079 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1080 return walletInfo.second !=
nullptr;
1083bool KWalletD::isOpen(
int handle)
1089 KWallet::Backend *rc = _wallets.
value(handle);
1091 if (rc ==
nullptr && ++_failed > 5) {
1094 }
else if (rc !=
nullptr) {
1098 return rc !=
nullptr;
1103 QString path = KWallet::Backend::getSaveLocation();
1104 QDir dir(path, QStringLiteral(
"*.kwl"));
1109 const auto list =
dir.entryInfoList();
1115 rc += decodeWalletName(fn);
1120void KWalletD::sync(
int handle,
const QString &appid)
1122 KWallet::Backend *b;
1125 if ((b = getWallet(appid, handle))) {
1126 QString wallet = b->walletName();
1131void KWalletD::timedOutSync(
int handle)
1133 _syncTimers.removeTimer(handle);
1134 if (_wallets.
contains(handle) && _wallets[handle]) {
1135 _wallets[handle]->sync(0);
1137 qDebug(
"wallet not found for sync!");
1141void KWalletD::doTransactionOpenCancelled(
const QString &appid,
const QString &wallet,
const QString &service)
1146 if (!_sessions.hasSession(appid)) {
1150 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1151 int handle = walletInfo.first;
1152 KWallet::Backend *b = walletInfo.second;
1153 if (handle != -1 && b) {
1155 internalClose(b, handle,
false);
1159 _sessions.removeSession(appid, service, handle);
1164 KWallet::Backend *b;
1166 if ((b = getWallet(appid, handle))) {
1167 return b->folderList();
1173bool KWalletD::hasFolder(
int handle,
const QString &f,
const QString &appid)
1175 KWallet::Backend *b;
1177 if ((b = getWallet(appid, handle))) {
1178 return b->hasFolder(f);
1184bool KWalletD::removeFolder(
int handle,
const QString &f,
const QString &appid)
1186 KWallet::Backend *b;
1188 if ((b = getWallet(appid, handle))) {
1189 bool rc = b->removeFolder(f);
1190 initiateSync(handle);
1191 Q_EMIT folderListUpdated(b->walletName());
1198bool KWalletD::createFolder(
int handle,
const QString &f,
const QString &appid)
1200 KWallet::Backend *b;
1202 if ((b = getWallet(appid, handle))) {
1203 bool rc = b->createFolder(f);
1204 initiateSync(handle);
1205 Q_EMIT folderListUpdated(b->walletName());
1214 KWallet::Backend *b;
1216 if ((b = getWallet(appid, handle))) {
1217 b->setFolder(folder);
1218 KWallet::Entry *e = b->readEntry(key);
1219 if (e && e->type() == KWallet::Wallet::Map) {
1227#if KWALLET_BUILD_DEPRECATED_SINCE(5, 72)
1228QVariantMap KWalletD::readMapList(
int handle,
const QString &folder,
const QString &key,
const QString &appid)
1230 KWallet::Backend *b;
1232 if ((b = getWallet(appid, handle))) {
1233 b->setFolder(folder);
1235 const auto lst = b->readEntryList(key);
1236 for (KWallet::Entry *entry : lst) {
1237 if (entry->type() == KWallet::Wallet::Map) {
1238 rc.insert(entry->key(), entry->map());
1244 return QVariantMap();
1248QVariantMap KWalletD::mapList(
int handle,
const QString &folder,
const QString &appid)
1252 KWallet::Backend *backend = getWallet(appid, handle);
1254 backend->setFolder(folder);
1256 for (KWallet::Entry *entry : lst) {
1257 if (entry->type() == KWallet::Wallet::Map) {
1258 rc.insert(entry->key(), entry->map());
1268 KWallet::Backend *b;
1270 if ((b = getWallet(appid, handle))) {
1271 b->setFolder(folder);
1272 KWallet::Entry *e = b->readEntry(key);
1281#if KWALLET_BUILD_DEPRECATED_SINCE(5, 72)
1282QVariantMap KWalletD::readEntryList(
int handle,
const QString &folder,
const QString &key,
const QString &appid)
1284 KWallet::Backend *b;
1286 if ((b = getWallet(appid, handle))) {
1287 b->setFolder(folder);
1289 const auto lst = b->readEntryList(key);
1290 for (KWallet::Entry *entry : lst) {
1291 rc.insert(entry->key(), entry->value());
1296 return QVariantMap();
1300QVariantMap KWalletD::entriesList(
int handle,
const QString &folder,
const QString &appid)
1304 KWallet::Backend *backend = getWallet(appid, handle);
1306 backend->setFolder(folder);
1308 for (KWallet::Entry *entry : lst) {
1309 rc.insert(entry->key(), entry->value());
1318 KWallet::Backend *b;
1320 if ((b = getWallet(appid, handle))) {
1321 b->setFolder(folder);
1322 return b->entryList();
1330 KWallet::Backend *b;
1332 if ((b = getWallet(appid, handle))) {
1333 b->setFolder(folder);
1334 KWallet::Entry *e = b->readEntry(key);
1335 if (e && e->type() == KWallet::Wallet::Password) {
1336 return e->password();
1343#if KWALLET_BUILD_DEPRECATED_SINCE(5, 72)
1344QVariantMap KWalletD::readPasswordList(
int handle,
const QString &folder,
const QString &key,
const QString &appid)
1346 KWallet::Backend *b;
1348 if ((b = getWallet(appid, handle))) {
1349 b->setFolder(folder);
1351 const auto lst = b->readEntryList(key);
1352 for (KWallet::Entry *entry : lst) {
1353 if (entry->type() == KWallet::Wallet::Password) {
1354 rc.insert(entry->key(), entry->password());
1360 return QVariantMap();
1364QVariantMap KWalletD::passwordList(
int handle,
const QString &folder,
const QString &appid)
1368 KWallet::Backend *backend = getWallet(appid, handle);
1370 backend->setFolder(folder);
1372 for (KWallet::Entry *entry : lst) {
1373 if (entry->type() == KWallet::Wallet::Password) {
1374 rc.insert(entry->key(), entry->password());
1384 KWallet::Backend *b;
1386 if ((b = getWallet(appid, handle))) {
1387 b->setFolder(folder);
1391 e.setType(KWallet::Wallet::Map);
1393 initiateSync(handle);
1394 emitFolderUpdated(b->walletName(), folder);
1395 emitEntryUpdated(b->walletName(), folder, key);
1404 KWallet::Backend *b;
1406 if ((b = getWallet(appid, handle))) {
1407 b->setFolder(folder);
1411 e.setType(KWallet::Wallet::Stream);
1413 initiateSync(handle);
1414 emitFolderUpdated(b->walletName(), folder);
1415 emitEntryUpdated(b->walletName(), folder, key);
1424 KWallet::Backend *b;
1426 if ((b = getWallet(appid, handle))) {
1427 b->setFolder(folder);
1431 e.setType(KWallet::Wallet::EntryType(entryType));
1433 initiateSync(handle);
1434 emitFolderUpdated(b->walletName(), folder);
1443 KWallet::Backend *b;
1445 if ((b = getWallet(appid, handle))) {
1446 b->setFolder(folder);
1450 e.setType(KWallet::Wallet::Password);
1452 initiateSync(handle);
1453 emitFolderUpdated(b->walletName(), folder);
1454 emitEntryUpdated(b->walletName(), folder, key);
1463 KWallet::Backend *b;
1465 if ((b = getWallet(appid, handle))) {
1466 if (!b->hasFolder(folder)) {
1467 return KWallet::Wallet::Unknown;
1469 b->setFolder(folder);
1470 if (b->hasEntry(key)) {
1471 return b->readEntry(key)->type();
1475 return KWallet::Wallet::Unknown;
1480 KWallet::Backend *b;
1482 if ((b = getWallet(appid, handle))) {
1483 if (!b->hasFolder(folder)) {
1486 b->setFolder(folder);
1487 return b->hasEntry(key);
1493int KWalletD::removeEntry(
int handle,
const QString &folder,
const QString &key,
const QString &appid)
1495 KWallet::Backend *b;
1497 if ((b = getWallet(appid, handle))) {
1498 if (!b->hasFolder(folder)) {
1501 b->setFolder(folder);
1502 bool rc = b->removeEntry(key);
1503 initiateSync(handle);
1504 emitFolderUpdated(b->walletName(), folder);
1505 emitEntryDeleted(b->walletName(), folder, key);
1512void KWalletD::slotServiceOwnerChanged(
const QString &name,
const QString &oldOwner,
const QString &newOwner)
1515 qCDebug(KWALLETD_LOG) <<
"slotServiceOwnerChanged " <<
name <<
", " << oldOwner <<
", " << newOwner;
1526 KWallet::Backend *b =
nullptr;
1529 for (
const KWalletAppHandlePair &s : sessremove) {
1530 b = getWallet(s.first, s.second);
1533 internalClose(b, s.second,
false);
1538 for (
const KWalletAppHandlePair &s : sessremove) {
1539 _sessions.removeSession(s.first, service, s.second);
1544 for (tit = _transactions.
begin(); tit != _transactions.
end(); ++tit) {
1545 if ((*tit)->tType == KWalletTransaction::Open && (*tit)->service == oldOwner) {
1554 if (_curtrans && _curtrans->tType == KWalletTransaction::Open && _curtrans->service == oldOwner) {
1555 qCDebug(KWALLETD_LOG) <<
"Cancelling current transaction!";
1556 _curtrans->cancelled =
true;
1561KWallet::Backend *KWalletD::getWallet(
const QString &appid,
int handle)
1567 KWallet::Backend *w = _wallets.
value(handle);
1570 if (_sessions.hasSession(appid, handle)) {
1574 _closeTimers.resetTimer(handle, _idleTime);
1580 if (++_failed > 5) {
1588void KWalletD::notifyFailures()
1590 if (!_showingFailureNotify) {
1591 _showingFailureNotify =
true;
1593 i18n(
"There have been repeated failed attempts to gain access to a wallet. An application may be misbehaving."),
1594 i18n(
"KDE Wallet Service"));
1595 _showingFailureNotify =
false;
1599void KWalletD::doCloseSignals(
int handle,
const QString &wallet)
1601 Q_EMIT walletClosed(handle);
1602 Q_EMIT walletClosedId(handle);
1604 Q_EMIT walletClosed(wallet);
1606 Q_EMIT allWalletsClosed();
1612 KWallet::Backend *b;
1614 if ((b = getWallet(appid, handle))) {
1615 b->setFolder(folder);
1616 int rc = b->renameEntry(oldName, newName);
1617 initiateSync(handle);
1618 emitFolderUpdated(b->walletName(), folder);
1619 emitEntryRenamed(b->walletName(), folder, oldName, newName);
1626int KWalletD::renameWallet(
const QString &oldName,
const QString &newName)
1628 const QPair<int, KWallet::Backend *> walletInfo = findWallet(oldName);
1629 return walletInfo.second->renameWallet(newName);
1634 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1635 return _sessions.getApplications(walletInfo.first);
1638bool KWalletD::disconnectApplication(
const QString &wallet,
const QString &application)
1640 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1641 int handle = walletInfo.first;
1642 KWallet::Backend *backend = walletInfo.second;
1644 if (handle != -1 && _sessions.hasSession(application, handle)) {
1645 int removed = _sessions.removeAllSessions(application, handle);
1647 for (
int i = 0; i < removed; ++i) {
1650 internalClose(backend, handle,
false);
1652 Q_EMIT applicationDisconnected(wallet, application);
1659void KWalletD::emitFolderUpdated(
const QString &wallet,
const QString &folder)
1661 Q_EMIT folderUpdated(wallet, folder);
1666 Q_EMIT entryUpdated(wallet, folder, key);
1671 Q_EMIT entryRenamed(wallet, folder, oldName, newName);
1676 Q_EMIT entryDeleted(wallet, folder, key);
1679void KWalletD::emitWalletListDirty()
1682 const auto lst = _wallets.
values();
1683 for (
auto i : lst) {
1684 if (!walletsInDisk.
contains(i->walletName())) {
1685 internalClose(i, _wallets.
key(i),
true,
false);
1688 Q_EMIT walletListDirty();
1691void KWalletD::reconfigure()
1693 KConfig cfg(QStringLiteral(
"kwalletrc"));
1695 _firstUse = walletGroup.readEntry(
"First Use",
true);
1696 _enabled = walletGroup.readEntry(
"Enabled",
true);
1697 _launchManager = walletGroup.readEntry(
"Launch Manager",
false);
1698 _leaveOpen = walletGroup.readEntry(
"Leave Open",
true);
1699 bool idleSave = _closeIdle;
1700 _closeIdle = walletGroup.readEntry(
"Close When Idle",
false);
1701 _openPrompt = walletGroup.readEntry(
"Prompt on Open",
false);
1702 int timeSave = _idleTime;
1704 _idleTime = walletGroup.readEntry(
"Idle Timeout", 10) * 60 * 1000;
1706 if (walletGroup.readEntry(
"Close on Screensaver",
false)) {
1713 if (screensaver && screensaver->isValid()) {
1714 screensaver->disconnect(SIGNAL(ActiveChanged(
bool)),
this, SLOT(screenSaverChanged(
bool)));
1722 if (_idleTime != timeSave) {
1723 Wallets::const_iterator it = _wallets.
constBegin();
1724 const Wallets::const_iterator
end = _wallets.
constEnd();
1725 for (; it !=
end; ++it) {
1726 _closeTimers.resetTimer(it.key(), _idleTime);
1731 Wallets::const_iterator it = _wallets.
constBegin();
1732 const Wallets::const_iterator
end = _wallets.
constEnd();
1733 for (; it !=
end; ++it) {
1734 _closeTimers.addTimer(it.key(), _idleTime);
1738 _closeTimers.clear();
1742 _implicitAllowMap.
clear();
1744 QStringList entries = autoAllowGroup.entryMap().keys();
1746 _implicitAllowMap[*i] = autoAllowGroup.readEntry(*i,
QStringList());
1750 _implicitDenyMap.
clear();
1752 entries = autoDenyGroup.entryMap().keys();
1754 _implicitDenyMap[*i] = autoDenyGroup.readEntry(*i,
QStringList());
1760 Wallets::const_iterator it = _wallets.
constBegin();
1761 internalClose(it.value(), it.key(),
true);
1767bool KWalletD::isEnabled()
const
1772bool KWalletD::folderDoesNotExist(
const QString &wallet,
const QString &folder)
1774 if (!wallets().contains(wallet)) {
1778 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1779 if (walletInfo.second) {
1780 return walletInfo.second->folderDoesNotExist(folder);
1783 KWallet::Backend *b =
new KWallet::Backend(wallet);
1785 bool rc = b->folderDoesNotExist(folder);
1792 if (!wallets().contains(wallet)) {
1796 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1797 if (walletInfo.second) {
1798 return walletInfo.second->entryDoesNotExist(folder, key);
1801 KWallet::Backend *b =
new KWallet::Backend(wallet);
1803 bool rc = b->entryDoesNotExist(folder, key);
1808bool KWalletD::implicitAllow(
const QString &wallet,
const QString &app)
1810 return _implicitAllowMap[wallet].
contains(app);
1813bool KWalletD::implicitDeny(
const QString &wallet,
const QString &app)
1815 return _implicitDenyMap[wallet].
contains(app);
1818void KWalletD::timedOutClose(
int id)
1820 KWallet::Backend *w = _wallets.
value(
id);
1822 internalClose(w,
id,
true);
1826void KWalletD::closeAllWallets()
1828 Wallets walletsCopy = _wallets;
1830 Wallets::const_iterator it = walletsCopy.
constBegin();
1831 const Wallets::const_iterator
end = walletsCopy.constEnd();
1832 for (; it !=
end; ++it) {
1833 internalClose(it.value(), it.key(),
true);
1836 walletsCopy.clear();
1842QString KWalletD::networkWallet()
1847QString KWalletD::localWallet()
1852void KWalletD::screenSaverChanged(
bool s)
1859void KWalletD::activatePasswordDialog()
1861 checkActiveDialog();
1864int KWalletD::pamOpen(
const QString &wallet,
const QByteArray &passwordHash,
int sessionTimeout)
1870 bool brandNew =
false;
1873 QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1874 int rc = walletInfo.first;
1878 if (_wallets.
count() > 20) {
1882 KWallet::Backend *b =
nullptr;
1885 if (!wallets().contains(wallet)) {
1886 b =
new KWallet::Backend(wallet);
1887 b->setCipherType(KWallet::BACKEND_CIPHER_BLOWFISH);
1890 b =
new KWallet::Backend(wallet);
1893 int openrc = b->openPreHashed(passwordHash);
1894 if (openrc != 0 || !b->isOpen()) {
1900 int handle = generateHandle();
1901 _wallets.
insert(handle, b);
1902 _syncTimers.addTimer(handle, _syncTime);
1907 if (sessionTimeout > 0) {
1908 _closeTimers.addTimer(handle, sessionTimeout);
1909 }
else if (_closeIdle) {
1910 _closeTimers.addTimer(handle, _idleTime);
1913 Q_EMIT walletCreated(wallet);
1915 Q_EMIT walletOpened(wallet);
1917 if (_wallets.
count() == 1 && _launchManager) {
1918 startManagerForKwalletd();
1926#include "moc_kwalletd.cpp"
KConfigGroup group(const QString &group)
void deleteEntry(const char *key, WriteConfigFlags pFlags=Normal)
void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags=Normal)
bool isEntryImmutable(const char *key) const
QString readEntry(const char *key, const char *aDefault=nullptr) const
void deleted(const QString &path)
void dirty(const QString &path)
void setBackgroundWarningColor(const QColor &color)
void setIcon(const QIcon &icon)
void setPrompt(const QString &prompt)
KNotificationAction * addAction(const QString &label)
void setWindow(QWindow *window)
void setText(const QString &text)
void setPrompt(const QString &prompt)
void setIcon(const QIcon &icon)
void setPassword(const QString &password)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
static const QString PasswordFolder()
The standardized name of the password folder.
static const QString NetworkWallet()
The name of the wallet used to store network passwords.
static const QString LocalWallet()
The name of the wallet used to store local passwords.
static const QString FormDataFolder()
The standardized name of the form data folder.
static bool isPlatformX11()
static void setMainWindow(QWindow *subwindow, const QString &mainwindow)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
KGUIADDONS_EXPORT QWindow * window(QObject *job)
QString path(const QString &relativePath)
void errorWId(WId parent_id, const QString &text, const QString &title=QString(), Options options=Notify)
void information(QWidget *parent, const QString &text, const QString &title=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
KIOCORE_EXPORT QString dir(const QString &fileClass)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
QString name(StandardAction id)
const QList< QKeySequence > & end()
void exit(int returnCode)
QDBusConnectionInterface * interface() const const
bool isConnected() const const
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
bool registerService(const QString &serviceName)
bool send(const QDBusMessage &message) const const
QDBusConnection sessionBus()
QDBusReply< QDBusConnectionInterface::RegisterServiceReply > registerService(const QString &serviceName, ServiceQueueOptions qoption, ServiceReplacementOptions roption)
QDBusConnection connection() const const
const QDBusMessage & message() const const
QDBusMessage createReply(const QList< QVariant > &arguments) const const
QString service() const const
void setDelayedReply(bool enable) const const
MessageType type() const const
void addWatchedService(const QString &newService)
bool removeWatchedService(const QString &service)
void serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner)
void setConnection(const QDBusConnection &connection)
bool exists() const const
const_iterator constBegin() const const
const_iterator constEnd() const const
bool contains(const Key &key) const const
qsizetype count() const const
iterator insert(const Key &key, const T &value)
bool isEmpty() const const
Key key(const T &value) const const
bool remove(const Key &key)
T value(const Key &key) const const
QList< T > values() const const
QIcon fromTheme(const QString &name)
void append(QList< T > &&value)
const_iterator constBegin() const const
const_iterator constEnd() const const
bool isEmpty() const const
qsizetype removeAll(const AT &t)
bool contains(const Key &key) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
QString findExecutable(const QString &executableName, const QStringList &paths)
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
bool isNull() const const
qsizetype length() const const
QString toHtmlEscaped() const const
QByteArray toUtf8() const const
void truncate(qsizetype position)
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)