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#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
47#include <gpgme++/key.h>
50#include <QApplication>
57#include "kwalletadaptor.h"
59static void startManagerForKwalletd()
62 QProcess::startDetached(QStringLiteral(
"kstart"), {QStringLiteral(
"kwalletmanager5"), QStringLiteral(
"--"), QStringLiteral(
"--kwalletd")});
64 QProcess::startDetached(QStringLiteral(
"kstart"), {QStringLiteral(
"kwalletmanager5"), QStringLiteral(
"--"), QStringLiteral(
"--kwalletd")});
70class KWalletTransaction
74 : tId(nextTransactionId)
81 if (nextTransactionId < 0) {
82 nextTransactionId = 0;
86 static int getTransactionId()
88 return nextTransactionId;
102 Type tType = Unknown;
107 bool cancelled =
false;
116 static int nextTransactionId;
119int KWalletTransaction::nextTransactionId = 0;
132 srand(time(
nullptr));
133 _showingFailureNotify =
false;
136 connect(&_closeTimers, &KTimeout::timedOut,
this, &KWalletD::timedOutClose);
137 connect(&_syncTimers, &KTimeout::timedOut,
this, &KWalletD::timedOutSync);
139 KConfig kwalletrc(QStringLiteral(
"kwalletrc"));
141 KConfigGroup cfgSecrets(&kwalletrc,
"org.freedesktop.secrets");
143 if (cfgWallet.readEntry<
bool>(
"apiEnabled",
true)) {
144 (void)
new KWalletAdaptor(
this);
153 new KWalletPortalSecrets(
this);
163 _dw->setObjectName(QStringLiteral(
"KWallet Directory Watcher"));
165 _dw->addDir(KWallet::Backend::getSaveLocation());
167 _dw->startScan(
true);
174 if (cfgSecrets.readEntry<
bool>(
"apiEnabled",
true)) {
175 _fdoService.reset(
new KWalletFreedesktopService(
this));
186 qDeleteAll(_transactions);
191 return KWallet::Backend::encodeWalletName(name);
196 return KWallet::Backend::decodeWalletName(mangledName);
200void KWalletD::connectToScreenSaver()
202 screensaver =
new QDBusInterface(
"org.freedesktop.ScreenSaver",
"/ScreenSaver",
"org.freedesktop.ScreenSaver");
203 if (!screensaver->isValid()) {
204 qCDebug(KWALLETD_LOG) <<
"Service org.freedesktop.ScreenSaver not found. Retrying in 10 seconds...";
208 connect(screensaver, SIGNAL(ActiveChanged(
bool)), SLOT(screenSaverChanged(
bool)));
209 qCDebug(KWALLETD_LOG) <<
"connected to screen saver service.";
214int KWalletD::generateHandle()
221 }
while (_wallets.
contains(rc) || rc == 0);
226QPair<int, KWallet::Backend *> KWalletD::findWallet(
const QString &walletName)
const
228 Wallets::const_iterator it = _wallets.
constBegin();
229 const Wallets::const_iterator
end = _wallets.
constEnd();
230 for (; it !=
end; ++it) {
231 if (it.value()->walletName() == walletName) {
232 return qMakePair(it.key(), it.value());
235 return qMakePair(-1,
static_cast<KWallet::Backend *
>(
nullptr));
238bool KWalletD::_processing =
false;
240void KWalletD::processTransactions()
249 while (!_transactions.
isEmpty()) {
253 assert(_curtrans->tType != KWalletTransaction::Unknown);
255 switch (_curtrans->tType) {
256 case KWalletTransaction::Open:
257 res = doTransactionOpen(_curtrans->appid, _curtrans->wallet, _curtrans->isPath, _curtrans->wId, _curtrans->modal, _curtrans->service);
264 for (it = _transactions.
begin(); it != _transactions.
end(); ++it) {
265 KWalletTransaction *x = *it;
266 if (_curtrans->appid == x->appid && x->tType == KWalletTransaction::Open && x->wallet == _curtrans->wallet && x->wId == _curtrans->wId) {
267 x->tType = KWalletTransaction::OpenFail;
270 }
else if (_curtrans->cancelled) {
273 KWalletTransaction *_xact =
new KWalletTransaction(_curtrans->connection);
274 _xact->tType = KWalletTransaction::CloseCancelled;
275 _xact->appid = _curtrans->appid;
276 _xact->wallet = _curtrans->wallet;
277 _xact->service = _curtrans->service;
278 _transactions.
append(_xact);
282 _curtrans->res = res;
283 Q_EMIT walletAsyncOpened(_curtrans->tId, res);
286 case KWalletTransaction::OpenFail:
289 Q_EMIT walletAsyncOpened(_curtrans->tId, -1);
292 case KWalletTransaction::ChangePassword:
293 doTransactionChangePassword(_curtrans->appid, _curtrans->wallet, _curtrans->wId);
296 case KWalletTransaction::CloseCancelled:
297 doTransactionOpenCancelled(_curtrans->appid, _curtrans->wallet, _curtrans->service);
300 case KWalletTransaction::Unknown:
310 reply << _curtrans->res;
311 _curtrans->connection.
send(reply);
322int KWalletD::openPath(
const QString &path, qlonglong wId,
const QString &appid)
324 int tId = openPathAsync(path, wId, appid,
false);
337int KWalletD::open(
const QString &wallet, qlonglong wId,
const QString &appid)
343 KWalletTransaction *xact =
new KWalletTransaction(
connection());
344 _transactions.
append(xact);
350 xact->wallet = wallet;
353 xact->tType = KWalletTransaction::Open;
354 xact->isPath =
false;
363int KWalletD::nextTransactionId()
const
365 return KWalletTransaction::getTransactionId();
368int KWalletD::openAsync(
const QString &wallet,
379 KWalletTransaction *xact =
new KWalletTransaction(
connection);
380 _transactions.
append(xact);
383 xact->wallet = wallet;
386 xact->tType = KWalletTransaction::Open;
387 xact->isPath =
false;
400int KWalletD::openAsync(
const QString &wallet, qlonglong wId,
const QString &appid,
bool handleSession)
405int KWalletD::openPathAsync(
const QString &path, qlonglong wId,
const QString &appid,
bool handleSession)
411 KWalletTransaction *xact =
new KWalletTransaction(
connection());
412 _transactions.
append(xact);
418 xact->tType = KWalletTransaction::Open;
433void KWalletD::setupDialog(
QWidget *dialog, WId wId,
const QString &appid,
bool modal)
441 qWarning() <<
"Using kwallet without parent window!";
443 qWarning() <<
"Application '" << appid <<
"' using kwallet without parent window!";
461 activeDialog = dialog;
475void KWalletD::checkActiveDialog()
484 activeDialog->show();
488 WId
window = activeDialog->winId();
496int KWalletD::doTransactionOpen(
const QString &appid,
const QString &wallet,
bool isPath, qlonglong wId,
bool modal,
const QString &service)
498 if (_firstUse && !isPath) {
502 KConfig kwalletrc(QStringLiteral(
"kwalletrc"));
504 cfg.writeEntry(
"Default Wallet", wallet);
507 KConfig kwalletrc(QStringLiteral(
"kwalletrc"));
510 cfg.writeEntry(
"First Use",
false);
570 int rc = internalOpen(appid, wallet, isPath, WId(wId), modal, service);
574int KWalletD::internalOpen(
const QString &appid,
const QString &wallet,
bool isPath, WId w,
bool modal,
const QString &service)
576 bool brandNew =
false;
580 thisApp = QStringLiteral(
"KDE System");
585 if (implicitDeny(wallet, thisApp)) {
589 QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
590 int rc = walletInfo.first;
592 if (_wallets.
count() > 20) {
593 qCDebug(KWALLETD_LOG) <<
"Too many wallets open.";
597 KWallet::Backend *b =
new KWallet::Backend(wallet, isPath);
599 bool emptyPass =
false;
600 if ((isPath &&
QFile::exists(wallet)) || (!isPath && KWallet::Backend::exists(wallet))) {
605 assert(b->cipherType() != KWallet::BACKEND_CIPHER_UNKNOWN);
606 if (b->cipherType() == KWallet::BACKEND_CIPHER_GPG) {
618 if (0 != pwless || !b->isOpen()) {
622 b =
new KWallet::Backend(wallet, isPath);
626 kpd->
setPrompt(
i18n(
"<qt>KDE has requested to open the wallet '<b>%1</b>'. Please enter the password for this wallet below.</qt>",
630 i18n(
"<qt>The application '<b>%1</b>' has requested to open the wallet '<b>%2</b>'. Please enter the password for this wallet "
657 actionText =
i18nc(
"Text of a button for switching to the (unnamed) application requesting a password",
"Switch there");
661 i18nc(
"Text of a button for switching to the application requesting a password",
"Switch to %1", appid.
toHtmlEscaped());
670 while (!b->isOpen()) {
671 setupDialog(kpd, w, appid, modal);
674 int rc = b->open(password.
toUtf8());
676 const auto errorStr = KWallet::Backend::openRCToString(rc);
677 qCWarning(KWALLETD_LOG) <<
"Failed to open wallet" << wallet << errorStr;
678 kpd->
setPrompt(
i18n(
"<qt>Error opening the wallet '<b>%1</b>'. Please try again.<br />(Error code %2: %3)</qt>",
699 KWallet::BackendCipherType newWalletType = KWallet::BACKEND_CIPHER_UNKNOWN;
701 std::shared_ptr<KWallet::KNewWalletDialog> newWalletDlg(
new KWallet::KNewWalletDialog(appid, wallet,
QWidget::find(w)));
703 setupDialog(newWalletDlg.get(), (WId)w, appid,
true);
705 newWalletType = newWalletDlg->isBlowfish() ? KWallet::BACKEND_CIPHER_BLOWFISH : KWallet::BACKEND_CIPHER_GPG;
706 gpgKey = newWalletDlg->gpgKey();
713 if (newWalletType == KWallet::BACKEND_CIPHER_GPG) {
714 b->setCipherType(newWalletType);
716 }
else if (newWalletType == KWallet::BACKEND_CIPHER_BLOWFISH) {
718 b->setCipherType(KWallet::BACKEND_CIPHER_BLOWFISH);
726 i18n(
"KDE has requested to open the wallet. This is used to store sensitive data in a "
727 "secure fashion. Please enter a password to use with this wallet or click cancel to "
728 "deny the application's request."));
731 i18n(
"<qt>The application '<b>%1</b>' has requested to open the KDE wallet. This is "
732 "used to store sensitive data in a secure fashion. Please enter a password to use "
733 "with this wallet or click cancel to deny the application's request.</qt>",
737 if (appid.
length() == 0) {
739 i18n(
"<qt>KDE has requested to create a new wallet named '<b>%1</b>'. Please choose a "
740 "password for this wallet, or cancel to deny the application's request.</qt>",
744 i18n(
"<qt>The application '<b>%1</b>' has requested to create a new wallet named '<b>%2</b>'. "
745 "Please choose a password for this wallet, or cancel to deny the application's request.</qt>",
754 while (!b->isOpen()) {
755 setupDialog(kpd, w, appid, modal);
758 int rc = b->open(password.
toUtf8());
760 kpd->
setPrompt(
i18n(
"<qt>Error opening the wallet '<b>%1</b>'. Please try again.<br />(Error code %2: %3)</qt>",
763 KWallet::Backend::openRCToString(rc)));
775 if ((b->cipherType() == KWallet::BACKEND_CIPHER_BLOWFISH) && !emptyPass && (password.
isNull() || !b->isOpen())) {
780 if (emptyPass && !isAuthorizedApp(appid, wallet, w)) {
785 _wallets.
insert(rc = generateHandle(), b);
786 _sessions.addSession(appid, service, rc);
787 _syncTimers.addTimer(rc, _syncTime);
796 _closeTimers.addTimer(rc, _idleTime);
799 Q_EMIT walletCreated(wallet);
801 Q_EMIT walletOpened(wallet);
802 if (_wallets.
count() == 1 && _launchManager) {
803 startManagerForKwalletd();
809 walletInfo.second->ref();
810 bool isAuthorized = _sessions.hasSession(appid, rc) || isAuthorizedApp(appid, wallet, w);
814 walletInfo = findWallet(wallet);
816 if (walletInfo.first != -1) {
817 walletInfo.second->deref();
819 internalClose(walletInfo.second, walletInfo.first,
false);
823 if (walletInfo.first != -1) {
824 _sessions.addSession(appid, service, rc);
835bool KWalletD::isAuthorizedApp(
const QString &appid,
const QString &wallet, WId w)
845 thisApp = QStringLiteral(
"KDE System");
850 if (!implicitAllow(wallet, thisApp)) {
853 KBetterThanKDialog *dialog =
new KBetterThanKDialog;
856 dialog->setLabel(
i18n(
"<qt>KDE has requested access to the open wallet '<b>%1</b>'.</qt>", wallet.
toHtmlEscaped()));
858 dialog->setLabel(
i18n(
"<qt>The application '<b>%1</b>' has requested access to the open wallet '<b>%2</b>'.</qt>",
862 setupDialog(dialog, w, appid,
false);
863 response = dialog->
exec();
868 if (response == 0 || response == 1) {
877 _implicitAllowMap[wallet] += thisApp;
882 }
else if (response == 3) {
887 _implicitDenyMap[wallet] += thisApp;
898int KWalletD::deleteWallet(
const QString &wallet)
901 QString path = KWallet::Backend::getSaveLocation() +
"/" + encodeWalletName(wallet) +
".kwl";
902 QString pathSalt = KWallet::Backend::getSaveLocation() +
"/" + encodeWalletName(wallet) +
".salt";
905 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
906 internalClose(walletInfo.second, walletInfo.first,
true);
908 Q_EMIT walletDeleted(wallet);
926void KWalletD::changePassword(
const QString &wallet, qlonglong wId,
const QString &appid)
928 KWalletTransaction *xact =
new KWalletTransaction(
connection());
936 xact->wallet = wallet;
939 xact->tType = KWalletTransaction::ChangePassword;
941 _transactions.
append(xact);
948void KWalletD::initiateSync(
int handle)
951 _syncTimers.addTimer(handle, _syncTime);
952 _syncTimers.resetTimer(handle, _syncTime);
955void KWalletD::doTransactionChangePassword(
const QString &appid,
const QString &wallet, qlonglong wId)
957 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
958 int handle = walletInfo.first;
959 KWallet::Backend *w = walletInfo.second;
961 bool reclose =
false;
963 handle = doTransactionOpen(appid, wallet,
false, wId,
false,
QLatin1String(
""));
966 i18n(
"Unable to open wallet. The wallet must be opened in order to change the password."),
967 i18n(
"KDE Wallet Service"));
971 w = _wallets.
value(handle);
978 if (w->cipherType() == KWallet::BACKEND_CIPHER_GPG) {
979 QString keyID = w->gpgKey().shortKeyID();
982 i18n(
"<qt>The <b>%1</b> wallet is encrypted using GPG key <b>%2</b>. Please use <b>GPG</b> tools (such "
983 "as <b>kleopatra</b>) to change the passphrase associated to that key.</qt>",
989 kpd->setPrompt(
i18n(
"<qt>Please choose a new password for the wallet '<b>%1</b>'.</qt>", wallet.
toHtmlEscaped()));
990 kpd->setWindowTitle(
i18n(
"KDE Wallet Service"));
991 kpd->setAllowEmptyPasswords(
true);
994 setupDialog(kpd, (WId)wId, appid,
false);
998 w->setPassword(p.
toUtf8());
999 int rc = w->close(
true);
1004 rc = w->open(p.
toUtf8());
1019 internalClose(w, handle,
true);
1023int KWalletD::close(
const QString &wallet,
bool force)
1025 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1026 int handle = walletInfo.first;
1027 KWallet::Backend *w = walletInfo.second;
1029 return internalClose(w, handle, force);
1032int KWalletD::internalClose(KWallet::Backend *
const w,
const int handle,
const bool force,
const bool saveBeforeClose)
1035 const QString &wallet = w->walletName();
1036 if ((w->refCount() == 0 && !_leaveOpen) || force) {
1038 _sessions.removeAllSessions(handle);
1040 _closeTimers.removeTimer(handle);
1042 _syncTimers.removeTimer(handle);
1044 w->close(saveBeforeClose);
1045 doCloseSignals(handle, wallet);
1055int KWalletD::close(
int handle,
bool force,
const QString &appid,
const QDBusMessage &message)
1057 KWallet::Backend *w = _wallets.
value(handle);
1060 if (_sessions.hasSession(appid, handle)) {
1062 bool removed = _sessions.removeSession(appid,
message.
service(), handle);
1064 if (removed || _sessions.removeSession(appid,
QLatin1String(
""), handle)) {
1067 return internalClose(w, handle, force);
1074int KWalletD::close(
int handle,
bool force,
const QString &appid)
1076 return close(handle, force, appid,
message());
1079bool KWalletD::isOpen(
const QString &wallet)
1081 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1082 return walletInfo.second !=
nullptr;
1085bool KWalletD::isOpen(
int handle)
1091 KWallet::Backend *rc = _wallets.
value(handle);
1093 if (rc ==
nullptr && ++_failed > 5) {
1096 }
else if (rc !=
nullptr) {
1100 return rc !=
nullptr;
1105 QString path = KWallet::Backend::getSaveLocation();
1106 QDir dir(path, QStringLiteral(
"*.kwl"));
1111 const auto list =
dir.entryInfoList();
1117 rc += decodeWalletName(fn);
1122void KWalletD::sync(
int handle,
const QString &appid)
1124 KWallet::Backend *b;
1127 if ((b = getWallet(appid, handle))) {
1128 QString wallet = b->walletName();
1133void KWalletD::timedOutSync(
int handle)
1135 _syncTimers.removeTimer(handle);
1136 if (_wallets.
contains(handle) && _wallets[handle]) {
1137 _wallets[handle]->sync(0);
1139 qDebug(
"wallet not found for sync!");
1143void KWalletD::doTransactionOpenCancelled(
const QString &appid,
const QString &wallet,
const QString &service)
1148 if (!_sessions.hasSession(appid)) {
1152 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1153 int handle = walletInfo.first;
1154 KWallet::Backend *b = walletInfo.second;
1155 if (handle != -1 && b) {
1157 internalClose(b, handle,
false);
1161 _sessions.removeSession(appid, service, handle);
1166 KWallet::Backend *b;
1168 if ((b = getWallet(appid, handle))) {
1169 return b->folderList();
1175bool KWalletD::hasFolder(
int handle,
const QString &f,
const QString &appid)
1177 KWallet::Backend *b;
1179 if ((b = getWallet(appid, handle))) {
1180 return b->hasFolder(f);
1186bool KWalletD::removeFolder(
int handle,
const QString &f,
const QString &appid)
1188 KWallet::Backend *b;
1190 if ((b = getWallet(appid, handle))) {
1191 bool rc = b->removeFolder(f);
1192 initiateSync(handle);
1193 Q_EMIT folderListUpdated(b->walletName());
1200bool KWalletD::createFolder(
int handle,
const QString &f,
const QString &appid)
1202 KWallet::Backend *b;
1204 if ((b = getWallet(appid, handle))) {
1205 bool rc = b->createFolder(f);
1206 initiateSync(handle);
1207 Q_EMIT folderListUpdated(b->walletName());
1216 KWallet::Backend *b;
1218 if ((b = getWallet(appid, handle))) {
1219 b->setFolder(folder);
1220 KWallet::Entry *e = b->readEntry(key);
1221 if (e && e->type() == KWallet::Wallet::Map) {
1229#if KWALLET_BUILD_DEPRECATED_SINCE(5, 72)
1230QVariantMap KWalletD::readMapList(
int handle,
const QString &folder,
const QString &key,
const QString &appid)
1232 KWallet::Backend *b;
1234 if ((b = getWallet(appid, handle))) {
1235 b->setFolder(folder);
1237 const auto lst = b->readEntryList(key);
1238 for (KWallet::Entry *entry : lst) {
1239 if (entry->type() == KWallet::Wallet::Map) {
1240 rc.insert(entry->key(), entry->map());
1246 return QVariantMap();
1250QVariantMap KWalletD::mapList(
int handle,
const QString &folder,
const QString &appid)
1254 KWallet::Backend *backend = getWallet(appid, handle);
1256 backend->setFolder(folder);
1258 for (KWallet::Entry *entry : lst) {
1259 if (entry->type() == KWallet::Wallet::Map) {
1260 rc.insert(entry->key(), entry->map());
1270 KWallet::Backend *b;
1272 if ((b = getWallet(appid, handle))) {
1273 b->setFolder(folder);
1274 KWallet::Entry *e = b->readEntry(key);
1283#if KWALLET_BUILD_DEPRECATED_SINCE(5, 72)
1284QVariantMap KWalletD::readEntryList(
int handle,
const QString &folder,
const QString &key,
const QString &appid)
1286 KWallet::Backend *b;
1288 if ((b = getWallet(appid, handle))) {
1289 b->setFolder(folder);
1291 const auto lst = b->readEntryList(key);
1292 for (KWallet::Entry *entry : lst) {
1293 rc.insert(entry->key(), entry->value());
1298 return QVariantMap();
1302QVariantMap KWalletD::entriesList(
int handle,
const QString &folder,
const QString &appid)
1306 KWallet::Backend *backend = getWallet(appid, handle);
1308 backend->setFolder(folder);
1310 for (KWallet::Entry *entry : lst) {
1311 rc.insert(entry->key(), entry->value());
1320 KWallet::Backend *b;
1322 if ((b = getWallet(appid, handle))) {
1323 b->setFolder(folder);
1324 return b->entryList();
1332 KWallet::Backend *b;
1334 if ((b = getWallet(appid, handle))) {
1335 b->setFolder(folder);
1336 KWallet::Entry *e = b->readEntry(key);
1337 if (e && e->type() == KWallet::Wallet::Password) {
1338 return e->password();
1345#if KWALLET_BUILD_DEPRECATED_SINCE(5, 72)
1346QVariantMap KWalletD::readPasswordList(
int handle,
const QString &folder,
const QString &key,
const QString &appid)
1348 KWallet::Backend *b;
1350 if ((b = getWallet(appid, handle))) {
1351 b->setFolder(folder);
1353 const auto lst = b->readEntryList(key);
1354 for (KWallet::Entry *entry : lst) {
1355 if (entry->type() == KWallet::Wallet::Password) {
1356 rc.insert(entry->key(), entry->password());
1362 return QVariantMap();
1366QVariantMap KWalletD::passwordList(
int handle,
const QString &folder,
const QString &appid)
1370 KWallet::Backend *backend = getWallet(appid, handle);
1372 backend->setFolder(folder);
1374 for (KWallet::Entry *entry : lst) {
1375 if (entry->type() == KWallet::Wallet::Password) {
1376 rc.insert(entry->key(), entry->password());
1386 KWallet::Backend *b;
1388 if ((b = getWallet(appid, handle))) {
1389 b->setFolder(folder);
1393 e.setType(KWallet::Wallet::Map);
1395 initiateSync(handle);
1396 emitFolderUpdated(b->walletName(), folder);
1397 emitEntryUpdated(b->walletName(), folder, key);
1406 KWallet::Backend *b;
1408 if ((b = getWallet(appid, handle))) {
1409 b->setFolder(folder);
1413 e.setType(KWallet::Wallet::Stream);
1415 initiateSync(handle);
1416 emitFolderUpdated(b->walletName(), folder);
1417 emitEntryUpdated(b->walletName(), folder, key);
1426 KWallet::Backend *b;
1428 if ((b = getWallet(appid, handle))) {
1429 b->setFolder(folder);
1433 e.setType(KWallet::Wallet::EntryType(entryType));
1435 initiateSync(handle);
1436 emitFolderUpdated(b->walletName(), folder);
1445 KWallet::Backend *b;
1447 if ((b = getWallet(appid, handle))) {
1448 b->setFolder(folder);
1452 e.setType(KWallet::Wallet::Password);
1454 initiateSync(handle);
1455 emitFolderUpdated(b->walletName(), folder);
1456 emitEntryUpdated(b->walletName(), folder, key);
1465 KWallet::Backend *b;
1467 if ((b = getWallet(appid, handle))) {
1468 if (!b->hasFolder(folder)) {
1469 return KWallet::Wallet::Unknown;
1471 b->setFolder(folder);
1472 if (b->hasEntry(key)) {
1473 return b->readEntry(key)->type();
1477 return KWallet::Wallet::Unknown;
1482 KWallet::Backend *b;
1484 if ((b = getWallet(appid, handle))) {
1485 if (!b->hasFolder(folder)) {
1488 b->setFolder(folder);
1489 return b->hasEntry(key);
1495int KWalletD::removeEntry(
int handle,
const QString &folder,
const QString &key,
const QString &appid)
1497 KWallet::Backend *b;
1499 if ((b = getWallet(appid, handle))) {
1500 if (!b->hasFolder(folder)) {
1503 b->setFolder(folder);
1504 bool rc = b->removeEntry(key);
1505 initiateSync(handle);
1506 emitFolderUpdated(b->walletName(), folder);
1507 emitEntryDeleted(b->walletName(), folder, key);
1514void KWalletD::slotServiceOwnerChanged(
const QString &name,
const QString &oldOwner,
const QString &newOwner)
1517 qCDebug(KWALLETD_LOG) <<
"slotServiceOwnerChanged " <<
name <<
", " << oldOwner <<
", " << newOwner;
1528 KWallet::Backend *b =
nullptr;
1531 for (
const KWalletAppHandlePair &s : sessremove) {
1532 b = getWallet(s.first, s.second);
1535 internalClose(b, s.second,
false);
1540 for (
const KWalletAppHandlePair &s : sessremove) {
1541 _sessions.removeSession(s.first, service, s.second);
1546 for (tit = _transactions.
begin(); tit != _transactions.
end(); ++tit) {
1547 if ((*tit)->tType == KWalletTransaction::Open && (*tit)->service == oldOwner) {
1556 if (_curtrans && _curtrans->tType == KWalletTransaction::Open && _curtrans->service == oldOwner) {
1557 qCDebug(KWALLETD_LOG) <<
"Cancelling current transaction!";
1558 _curtrans->cancelled =
true;
1563KWallet::Backend *KWalletD::getWallet(
const QString &appid,
int handle)
1569 KWallet::Backend *w = _wallets.
value(handle);
1572 if (_sessions.hasSession(appid, handle)) {
1576 _closeTimers.resetTimer(handle, _idleTime);
1582 if (++_failed > 5) {
1590void KWalletD::notifyFailures()
1592 if (!_showingFailureNotify) {
1593 _showingFailureNotify =
true;
1595 i18n(
"There have been repeated failed attempts to gain access to a wallet. An application may be misbehaving."),
1596 i18n(
"KDE Wallet Service"));
1597 _showingFailureNotify =
false;
1601void KWalletD::doCloseSignals(
int handle,
const QString &wallet)
1603 Q_EMIT walletClosed(handle);
1604 Q_EMIT walletClosedId(handle);
1606 Q_EMIT walletClosed(wallet);
1608 Q_EMIT allWalletsClosed();
1614 KWallet::Backend *b;
1616 if ((b = getWallet(appid, handle))) {
1617 b->setFolder(folder);
1618 int rc = b->renameEntry(oldName, newName);
1619 initiateSync(handle);
1620 emitFolderUpdated(b->walletName(), folder);
1621 emitEntryRenamed(b->walletName(), folder, oldName, newName);
1628int KWalletD::renameWallet(
const QString &oldName,
const QString &newName)
1630 const QPair<int, KWallet::Backend *> walletInfo = findWallet(oldName);
1631 return walletInfo.second->renameWallet(newName);
1636 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1637 return _sessions.getApplications(walletInfo.first);
1640bool KWalletD::disconnectApplication(
const QString &wallet,
const QString &application)
1642 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1643 int handle = walletInfo.first;
1644 KWallet::Backend *backend = walletInfo.second;
1646 if (handle != -1 && _sessions.hasSession(application, handle)) {
1647 int removed = _sessions.removeAllSessions(application, handle);
1649 for (
int i = 0; i < removed; ++i) {
1652 internalClose(backend, handle,
false);
1654 Q_EMIT applicationDisconnected(wallet, application);
1661void KWalletD::emitFolderUpdated(
const QString &wallet,
const QString &folder)
1663 Q_EMIT folderUpdated(wallet, folder);
1668 Q_EMIT entryUpdated(wallet, folder, key);
1673 Q_EMIT entryRenamed(wallet, folder, oldName, newName);
1678 Q_EMIT entryDeleted(wallet, folder, key);
1681void KWalletD::emitWalletListDirty()
1684 const auto lst = _wallets.
values();
1685 for (
auto i : lst) {
1686 if (!walletsInDisk.
contains(i->walletName())) {
1687 internalClose(i, _wallets.
key(i),
true,
false);
1690 Q_EMIT walletListDirty();
1693void KWalletD::reconfigure()
1695 KConfig cfg(QStringLiteral(
"kwalletrc"));
1697 _firstUse = walletGroup.readEntry(
"First Use",
true);
1698 _enabled = walletGroup.readEntry(
"Enabled",
true);
1699 _launchManager = walletGroup.readEntry(
"Launch Manager",
false);
1700 _leaveOpen = walletGroup.readEntry(
"Leave Open",
true);
1701 bool idleSave = _closeIdle;
1702 _closeIdle = walletGroup.readEntry(
"Close When Idle",
false);
1703 _openPrompt = walletGroup.readEntry(
"Prompt on Open",
false);
1704 int timeSave = _idleTime;
1706 _idleTime = walletGroup.readEntry(
"Idle Timeout", 10) * 60 * 1000;
1708 if (walletGroup.readEntry(
"Close on Screensaver",
false)) {
1715 if (screensaver && screensaver->isValid()) {
1716 screensaver->disconnect(SIGNAL(ActiveChanged(
bool)),
this, SLOT(screenSaverChanged(
bool)));
1724 if (_idleTime != timeSave) {
1725 Wallets::const_iterator it = _wallets.
constBegin();
1726 const Wallets::const_iterator
end = _wallets.
constEnd();
1727 for (; it !=
end; ++it) {
1728 _closeTimers.resetTimer(it.key(), _idleTime);
1733 Wallets::const_iterator it = _wallets.
constBegin();
1734 const Wallets::const_iterator
end = _wallets.
constEnd();
1735 for (; it !=
end; ++it) {
1736 _closeTimers.addTimer(it.key(), _idleTime);
1740 _closeTimers.clear();
1744 _implicitAllowMap.
clear();
1746 QStringList entries = autoAllowGroup.entryMap().keys();
1748 _implicitAllowMap[*i] = autoAllowGroup.readEntry(*i,
QStringList());
1752 _implicitDenyMap.
clear();
1754 entries = autoDenyGroup.entryMap().keys();
1756 _implicitDenyMap[*i] = autoDenyGroup.readEntry(*i,
QStringList());
1762 Wallets::const_iterator it = _wallets.
constBegin();
1763 internalClose(it.value(), it.key(),
true);
1769bool KWalletD::isEnabled()
const
1774bool KWalletD::folderDoesNotExist(
const QString &wallet,
const QString &folder)
1776 if (!wallets().contains(wallet)) {
1780 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1781 if (walletInfo.second) {
1782 return walletInfo.second->folderDoesNotExist(folder);
1785 KWallet::Backend *b =
new KWallet::Backend(wallet);
1787 bool rc = b->folderDoesNotExist(folder);
1794 if (!wallets().contains(wallet)) {
1798 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1799 if (walletInfo.second) {
1800 return walletInfo.second->entryDoesNotExist(folder, key);
1803 KWallet::Backend *b =
new KWallet::Backend(wallet);
1805 bool rc = b->entryDoesNotExist(folder, key);
1810bool KWalletD::implicitAllow(
const QString &wallet,
const QString &app)
1812 return _implicitAllowMap[wallet].
contains(app);
1815bool KWalletD::implicitDeny(
const QString &wallet,
const QString &app)
1817 return _implicitDenyMap[wallet].
contains(app);
1820void KWalletD::timedOutClose(
int id)
1822 KWallet::Backend *w = _wallets.
value(
id);
1824 internalClose(w,
id,
true);
1828void KWalletD::closeAllWallets()
1830 Wallets walletsCopy = _wallets;
1832 Wallets::const_iterator it = walletsCopy.
constBegin();
1833 const Wallets::const_iterator
end = walletsCopy.constEnd();
1834 for (; it !=
end; ++it) {
1835 internalClose(it.value(), it.key(),
true);
1838 walletsCopy.clear();
1844QString KWalletD::networkWallet()
1849QString KWalletD::localWallet()
1854void KWalletD::screenSaverChanged(
bool s)
1861void KWalletD::activatePasswordDialog()
1863 checkActiveDialog();
1866int KWalletD::pamOpen(
const QString &wallet,
const QByteArray &passwordHash,
int sessionTimeout)
1872 bool brandNew =
false;
1875 QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1876 int rc = walletInfo.first;
1880 if (_wallets.
count() > 20) {
1884 KWallet::Backend *b =
nullptr;
1887 if (!wallets().contains(wallet)) {
1888 b =
new KWallet::Backend(wallet);
1889 b->setCipherType(KWallet::BACKEND_CIPHER_BLOWFISH);
1892 b =
new KWallet::Backend(wallet);
1895 int openrc = b->openPreHashed(passwordHash);
1896 if (openrc != 0 || !b->isOpen()) {
1902 int handle = generateHandle();
1903 _wallets.
insert(handle, b);
1904 _syncTimers.addTimer(handle, _syncTime);
1909 if (sessionTimeout > 0) {
1910 _closeTimers.addTimer(handle, sessionTimeout);
1911 }
else if (_closeIdle) {
1912 _closeTimers.addTimer(handle, _idleTime);
1915 Q_EMIT walletCreated(wallet);
1917 Q_EMIT walletOpened(wallet);
1919 if (_wallets.
count() == 1 && _launchManager) {
1920 startManagerForKwalletd();
1928#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)
const QList< QKeySequence > & end()
QString name(StandardShortcut id)
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)