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 "kwalletwizard.h"
21#include "knewwalletdialog.h"
24#include <KColorScheme>
26#include <KConfigGroup>
28#include <KLocalizedString>
30#include <KNewPasswordDialog>
31#include <KNotification>
32#include <KPasswordDialog>
33#include <KPluginFactory>
34#include <KSharedConfig>
35#include <kwalletentry.h>
36#include <kwindowsystem.h>
38#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
46#include <gpgme++/key.h>
49#include <QApplication>
56#include "kwalletadaptor.h"
58static void startManagerForKwalletd()
61 QProcess::startDetached(QStringLiteral(
"kstart"), {QStringLiteral(
"kwalletmanager5"), QStringLiteral(
"--"), QStringLiteral(
"--kwalletd")});
63 QProcess::startDetached(QStringLiteral(
"kstart"), {QStringLiteral(
"kwalletmanager5"), QStringLiteral(
"--"), QStringLiteral(
"--kwalletd")});
69class KWalletTransaction
73 : tId(nextTransactionId)
80 if (nextTransactionId < 0) {
81 nextTransactionId = 0;
85 static int getTransactionId()
87 return nextTransactionId;
101 Type tType = Unknown;
106 bool cancelled =
false;
115 static int nextTransactionId;
118int KWalletTransaction::nextTransactionId = 0;
131 srand(time(
nullptr));
132 _showingFailureNotify =
false;
135 connect(&_closeTimers, &KTimeout::timedOut,
this, &KWalletD::timedOutClose);
136 connect(&_syncTimers, &KTimeout::timedOut,
this, &KWalletD::timedOutSync);
138 KConfig kwalletrc(QStringLiteral(
"kwalletrc"));
140 KConfigGroup cfgSecrets(&kwalletrc,
"org.freedesktop.secrets");
142 if (cfgWallet.readEntry<
bool>(
"apiEnabled",
true)) {
143 (void)
new KWalletAdaptor(
this);
160 _dw->setObjectName(QStringLiteral(
"KWallet Directory Watcher"));
162 _dw->addDir(KWallet::Backend::getSaveLocation());
164 _dw->startScan(
true);
171 if (cfgSecrets.readEntry<
bool>(
"apiEnabled",
true)) {
172 _fdoService.reset(
new KWalletFreedesktopService(
this));
183 qDeleteAll(_transactions);
188 return KWallet::Backend::encodeWalletName(name);
193 return KWallet::Backend::decodeWalletName(mangledName);
197void KWalletD::connectToScreenSaver()
199 screensaver =
new QDBusInterface(
"org.freedesktop.ScreenSaver",
"/ScreenSaver",
"org.freedesktop.ScreenSaver");
200 if (!screensaver->isValid()) {
201 qCDebug(KWALLETD_LOG) <<
"Service org.freedesktop.ScreenSaver not found. Retrying in 10 seconds...";
205 connect(screensaver, SIGNAL(ActiveChanged(
bool)), SLOT(screenSaverChanged(
bool)));
206 qCDebug(KWALLETD_LOG) <<
"connected to screen saver service.";
211int KWalletD::generateHandle()
218 }
while (_wallets.
contains(rc) || rc == 0);
223QPair<int, KWallet::Backend *> KWalletD::findWallet(
const QString &walletName)
const
225 Wallets::const_iterator it = _wallets.
constBegin();
226 const Wallets::const_iterator
end = _wallets.
constEnd();
227 for (; it !=
end; ++it) {
228 if (it.value()->walletName() == walletName) {
229 return qMakePair(it.key(), it.value());
232 return qMakePair(-1,
static_cast<KWallet::Backend *
>(
nullptr));
235bool KWalletD::_processing =
false;
237void KWalletD::processTransactions()
246 while (!_transactions.
isEmpty()) {
250 assert(_curtrans->tType != KWalletTransaction::Unknown);
252 switch (_curtrans->tType) {
253 case KWalletTransaction::Open:
254 res = doTransactionOpen(_curtrans->appid, _curtrans->wallet, _curtrans->isPath, _curtrans->wId, _curtrans->modal, _curtrans->service);
261 for (it = _transactions.
begin(); it != _transactions.
end(); ++it) {
262 KWalletTransaction *x = *it;
263 if (_curtrans->appid == x->appid && x->tType == KWalletTransaction::Open && x->wallet == _curtrans->wallet && x->wId == _curtrans->wId) {
264 x->tType = KWalletTransaction::OpenFail;
267 }
else if (_curtrans->cancelled) {
270 KWalletTransaction *_xact =
new KWalletTransaction(_curtrans->connection);
271 _xact->tType = KWalletTransaction::CloseCancelled;
272 _xact->appid = _curtrans->appid;
273 _xact->wallet = _curtrans->wallet;
274 _xact->service = _curtrans->service;
275 _transactions.
append(_xact);
279 _curtrans->res = res;
280 Q_EMIT walletAsyncOpened(_curtrans->tId, res);
283 case KWalletTransaction::OpenFail:
286 Q_EMIT walletAsyncOpened(_curtrans->tId, -1);
289 case KWalletTransaction::ChangePassword:
290 doTransactionChangePassword(_curtrans->appid, _curtrans->wallet, _curtrans->wId);
293 case KWalletTransaction::CloseCancelled:
294 doTransactionOpenCancelled(_curtrans->appid, _curtrans->wallet, _curtrans->service);
297 case KWalletTransaction::Unknown:
307 reply << _curtrans->res;
308 _curtrans->connection.
send(reply);
319int KWalletD::openPath(
const QString &path, qlonglong wId,
const QString &appid)
321 int tId = openPathAsync(path, wId, appid,
false);
334int KWalletD::open(
const QString &wallet, qlonglong wId,
const QString &appid)
340 KWalletTransaction *xact =
new KWalletTransaction(
connection());
341 _transactions.
append(xact);
347 xact->wallet = wallet;
350 xact->tType = KWalletTransaction::Open;
351 xact->isPath =
false;
360int KWalletD::nextTransactionId()
const
362 return KWalletTransaction::getTransactionId();
365int KWalletD::openAsync(
const QString &wallet,
376 KWalletTransaction *xact =
new KWalletTransaction(
connection);
377 _transactions.
append(xact);
380 xact->wallet = wallet;
383 xact->tType = KWalletTransaction::Open;
384 xact->isPath =
false;
397int KWalletD::openAsync(
const QString &wallet, qlonglong wId,
const QString &appid,
bool handleSession)
402int KWalletD::openPathAsync(
const QString &path, qlonglong wId,
const QString &appid,
bool handleSession)
408 KWalletTransaction *xact =
new KWalletTransaction(
connection());
409 _transactions.
append(xact);
415 xact->tType = KWalletTransaction::Open;
430void KWalletD::setupDialog(
QWidget *dialog, WId wId,
const QString &appid,
bool modal)
438 qWarning() <<
"Using kwallet without parent window!";
440 qWarning() <<
"Application '" << appid <<
"' using kwallet without parent window!";
458 activeDialog = dialog;
472void KWalletD::checkActiveDialog()
481 activeDialog->show();
485 WId
window = activeDialog->winId();
493int KWalletD::doTransactionOpen(
const QString &appid,
const QString &wallet,
bool isPath, qlonglong wId,
bool modal,
const QString &service)
495 if (_firstUse && !isPath) {
499 KConfig kwalletrc(QStringLiteral(
"kwalletrc"));
501 cfg.writeEntry(
"Default Wallet", wallet);
504 KConfig kwalletrc(QStringLiteral(
"kwalletrc"));
507 cfg.writeEntry(
"First Use",
false);
567 int rc = internalOpen(appid, wallet, isPath, WId(wId), modal, service);
571int KWalletD::internalOpen(
const QString &appid,
const QString &wallet,
bool isPath, WId w,
bool modal,
const QString &service)
573 bool brandNew =
false;
577 thisApp = QStringLiteral(
"KDE System");
582 if (implicitDeny(wallet, thisApp)) {
586 QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
587 int rc = walletInfo.first;
589 if (_wallets.
count() > 20) {
590 qCDebug(KWALLETD_LOG) <<
"Too many wallets open.";
594 KWallet::Backend *b =
new KWallet::Backend(wallet, isPath);
596 bool emptyPass =
false;
597 if ((isPath &&
QFile::exists(wallet)) || (!isPath && KWallet::Backend::exists(wallet))) {
602 assert(b->cipherType() != KWallet::BACKEND_CIPHER_UNKNOWN);
603 if (b->cipherType() == KWallet::BACKEND_CIPHER_GPG) {
615 if (0 != pwless || !b->isOpen()) {
619 b =
new KWallet::Backend(wallet, isPath);
623 kpd->
setPrompt(
i18n(
"<qt>KDE has requested to open the wallet '<b>%1</b>'. Please enter the password for this wallet below.</qt>",
627 i18n(
"<qt>The application '<b>%1</b>' has requested to open the wallet '<b>%2</b>'. Please enter the password for this wallet "
654 actionText =
i18nc(
"Text of a button for switching to the (unnamed) application requesting a password",
"Switch there");
658 i18nc(
"Text of a button for switching to the application requesting a password",
"Switch to %1", appid.
toHtmlEscaped());
667 while (!b->isOpen()) {
668 setupDialog(kpd, w, appid, modal);
671 int rc = b->open(password.
toUtf8());
673 const auto errorStr = KWallet::Backend::openRCToString(rc);
674 qCWarning(KWALLETD_LOG) <<
"Failed to open wallet" << wallet << errorStr;
675 kpd->
setPrompt(
i18n(
"<qt>Error opening the wallet '<b>%1</b>'. Please try again.<br />(Error code %2: %3)</qt>",
696 KWallet::BackendCipherType newWalletType = KWallet::BACKEND_CIPHER_UNKNOWN;
698 std::shared_ptr<KWallet::KNewWalletDialog> newWalletDlg(
new KWallet::KNewWalletDialog(appid, wallet,
QWidget::find(w)));
700 setupDialog(newWalletDlg.get(), (WId)w, appid,
true);
702 newWalletType = newWalletDlg->isBlowfish() ? KWallet::BACKEND_CIPHER_BLOWFISH : KWallet::BACKEND_CIPHER_GPG;
703 gpgKey = newWalletDlg->gpgKey();
710 if (newWalletType == KWallet::BACKEND_CIPHER_GPG) {
711 b->setCipherType(newWalletType);
713 }
else if (newWalletType == KWallet::BACKEND_CIPHER_BLOWFISH) {
715 b->setCipherType(KWallet::BACKEND_CIPHER_BLOWFISH);
723 i18n(
"KDE has requested to open the wallet. This is used to store sensitive data in a "
724 "secure fashion. Please enter a password to use with this wallet or click cancel to "
725 "deny the application's request."));
728 i18n(
"<qt>The application '<b>%1</b>' has requested to open the KDE wallet. This is "
729 "used to store sensitive data in a secure fashion. Please enter a password to use "
730 "with this wallet or click cancel to deny the application's request.</qt>",
734 if (appid.
length() == 0) {
736 i18n(
"<qt>KDE has requested to create a new wallet named '<b>%1</b>'. Please choose a "
737 "password for this wallet, or cancel to deny the application's request.</qt>",
741 i18n(
"<qt>The application '<b>%1</b>' has requested to create a new wallet named '<b>%2</b>'. "
742 "Please choose a password for this wallet, or cancel to deny the application's request.</qt>",
751 while (!b->isOpen()) {
752 setupDialog(kpd, w, appid, modal);
755 int rc = b->open(password.
toUtf8());
757 kpd->
setPrompt(
i18n(
"<qt>Error opening the wallet '<b>%1</b>'. Please try again.<br />(Error code %2: %3)</qt>",
760 KWallet::Backend::openRCToString(rc)));
772 if ((b->cipherType() == KWallet::BACKEND_CIPHER_BLOWFISH) && !emptyPass && (password.
isNull() || !b->isOpen())) {
777 if (emptyPass && !isAuthorizedApp(appid, wallet, w)) {
782 _wallets.
insert(rc = generateHandle(), b);
783 _sessions.addSession(appid, service, rc);
784 _syncTimers.addTimer(rc, _syncTime);
793 _closeTimers.addTimer(rc, _idleTime);
796 Q_EMIT walletCreated(wallet);
798 Q_EMIT walletOpened(wallet);
799 if (_wallets.
count() == 1 && _launchManager) {
800 startManagerForKwalletd();
806 walletInfo.second->ref();
807 bool isAuthorized = _sessions.hasSession(appid, rc) || isAuthorizedApp(appid, wallet, w);
811 walletInfo = findWallet(wallet);
813 if (walletInfo.first != -1) {
814 walletInfo.second->deref();
816 internalClose(walletInfo.second, walletInfo.first,
false);
820 if (walletInfo.first != -1) {
821 _sessions.addSession(appid, service, rc);
832bool KWalletD::isAuthorizedApp(
const QString &appid,
const QString &wallet, WId w)
842 thisApp = QStringLiteral(
"KDE System");
847 if (!implicitAllow(wallet, thisApp)) {
850 KBetterThanKDialog *dialog =
new KBetterThanKDialog;
853 dialog->setLabel(
i18n(
"<qt>KDE has requested access to the open wallet '<b>%1</b>'.</qt>", wallet.
toHtmlEscaped()));
855 dialog->setLabel(
i18n(
"<qt>The application '<b>%1</b>' has requested access to the open wallet '<b>%2</b>'.</qt>",
859 setupDialog(dialog, w, appid,
false);
860 response = dialog->
exec();
865 if (response == 0 || response == 1) {
874 _implicitAllowMap[wallet] += thisApp;
879 }
else if (response == 3) {
884 _implicitDenyMap[wallet] += thisApp;
895int KWalletD::deleteWallet(
const QString &wallet)
898 QString path = KWallet::Backend::getSaveLocation() +
"/" + encodeWalletName(wallet) +
".kwl";
899 QString pathSalt = KWallet::Backend::getSaveLocation() +
"/" + encodeWalletName(wallet) +
".salt";
902 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
903 internalClose(walletInfo.second, walletInfo.first,
true);
905 Q_EMIT walletDeleted(wallet);
923void KWalletD::changePassword(
const QString &wallet, qlonglong wId,
const QString &appid)
925 KWalletTransaction *xact =
new KWalletTransaction(
connection());
933 xact->wallet = wallet;
936 xact->tType = KWalletTransaction::ChangePassword;
938 _transactions.
append(xact);
945void KWalletD::initiateSync(
int handle)
948 _syncTimers.addTimer(handle, _syncTime);
949 _syncTimers.resetTimer(handle, _syncTime);
952void KWalletD::doTransactionChangePassword(
const QString &appid,
const QString &wallet, qlonglong wId)
954 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
955 int handle = walletInfo.first;
956 KWallet::Backend *w = walletInfo.second;
958 bool reclose =
false;
960 handle = doTransactionOpen(appid, wallet,
false, wId,
false,
QLatin1String(
""));
963 i18n(
"Unable to open wallet. The wallet must be opened in order to change the password."),
964 i18n(
"KDE Wallet Service"));
968 w = _wallets.
value(handle);
975 if (w->cipherType() == KWallet::BACKEND_CIPHER_GPG) {
976 QString keyID = w->gpgKey().shortKeyID();
979 i18n(
"<qt>The <b>%1</b> wallet is encrypted using GPG key <b>%2</b>. Please use <b>GPG</b> tools (such "
980 "as <b>kleopatra</b>) to change the passphrase associated to that key.</qt>",
986 kpd->setPrompt(
i18n(
"<qt>Please choose a new password for the wallet '<b>%1</b>'.</qt>", wallet.
toHtmlEscaped()));
987 kpd->setWindowTitle(
i18n(
"KDE Wallet Service"));
988 kpd->setAllowEmptyPasswords(
true);
991 setupDialog(kpd, (WId)wId, appid,
false);
995 w->setPassword(p.
toUtf8());
996 int rc = w->close(
true);
1001 rc = w->open(p.
toUtf8());
1016 internalClose(w, handle,
true);
1020int KWalletD::close(
const QString &wallet,
bool force)
1022 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1023 int handle = walletInfo.first;
1024 KWallet::Backend *w = walletInfo.second;
1026 return internalClose(w, handle, force);
1029int KWalletD::internalClose(KWallet::Backend *
const w,
const int handle,
const bool force,
const bool saveBeforeClose)
1032 const QString &wallet = w->walletName();
1033 if ((w->refCount() == 0 && !_leaveOpen) || force) {
1035 _sessions.removeAllSessions(handle);
1037 _closeTimers.removeTimer(handle);
1039 _syncTimers.removeTimer(handle);
1041 w->close(saveBeforeClose);
1042 doCloseSignals(handle, wallet);
1052int KWalletD::close(
int handle,
bool force,
const QString &appid,
const QDBusMessage &message)
1054 KWallet::Backend *w = _wallets.
value(handle);
1057 if (_sessions.hasSession(appid, handle)) {
1059 bool removed = _sessions.removeSession(appid,
message.
service(), handle);
1061 if (removed || _sessions.removeSession(appid,
QLatin1String(
""), handle)) {
1064 return internalClose(w, handle, force);
1071int KWalletD::close(
int handle,
bool force,
const QString &appid)
1073 return close(handle, force, appid,
message());
1076bool KWalletD::isOpen(
const QString &wallet)
1078 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1079 return walletInfo.second !=
nullptr;
1082bool KWalletD::isOpen(
int handle)
1088 KWallet::Backend *rc = _wallets.
value(handle);
1090 if (rc ==
nullptr && ++_failed > 5) {
1093 }
else if (rc !=
nullptr) {
1097 return rc !=
nullptr;
1102 QString path = KWallet::Backend::getSaveLocation();
1103 QDir dir(path, QStringLiteral(
"*.kwl"));
1108 const auto list =
dir.entryInfoList();
1114 rc += decodeWalletName(fn);
1119void KWalletD::sync(
int handle,
const QString &appid)
1121 KWallet::Backend *b;
1124 if ((b = getWallet(appid, handle))) {
1125 QString wallet = b->walletName();
1130void KWalletD::timedOutSync(
int handle)
1132 _syncTimers.removeTimer(handle);
1133 if (_wallets.
contains(handle) && _wallets[handle]) {
1134 _wallets[handle]->sync(0);
1136 qDebug(
"wallet not found for sync!");
1140void KWalletD::doTransactionOpenCancelled(
const QString &appid,
const QString &wallet,
const QString &service)
1145 if (!_sessions.hasSession(appid)) {
1149 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1150 int handle = walletInfo.first;
1151 KWallet::Backend *b = walletInfo.second;
1152 if (handle != -1 && b) {
1154 internalClose(b, handle,
false);
1158 _sessions.removeSession(appid, service, handle);
1163 KWallet::Backend *b;
1165 if ((b = getWallet(appid, handle))) {
1166 return b->folderList();
1172bool KWalletD::hasFolder(
int handle,
const QString &f,
const QString &appid)
1174 KWallet::Backend *b;
1176 if ((b = getWallet(appid, handle))) {
1177 return b->hasFolder(f);
1183bool KWalletD::removeFolder(
int handle,
const QString &f,
const QString &appid)
1185 KWallet::Backend *b;
1187 if ((b = getWallet(appid, handle))) {
1188 bool rc = b->removeFolder(f);
1189 initiateSync(handle);
1190 Q_EMIT folderListUpdated(b->walletName());
1197bool KWalletD::createFolder(
int handle,
const QString &f,
const QString &appid)
1199 KWallet::Backend *b;
1201 if ((b = getWallet(appid, handle))) {
1202 bool rc = b->createFolder(f);
1203 initiateSync(handle);
1204 Q_EMIT folderListUpdated(b->walletName());
1213 KWallet::Backend *b;
1215 if ((b = getWallet(appid, handle))) {
1216 b->setFolder(folder);
1217 KWallet::Entry *e = b->readEntry(key);
1218 if (e && e->type() == KWallet::Wallet::Map) {
1226#if KWALLET_BUILD_DEPRECATED_SINCE(5, 72)
1227QVariantMap KWalletD::readMapList(
int handle,
const QString &folder,
const QString &key,
const QString &appid)
1229 KWallet::Backend *b;
1231 if ((b = getWallet(appid, handle))) {
1232 b->setFolder(folder);
1234 const auto lst = b->readEntryList(key);
1235 for (KWallet::Entry *entry : lst) {
1236 if (entry->type() == KWallet::Wallet::Map) {
1237 rc.insert(entry->key(), entry->map());
1243 return QVariantMap();
1247QVariantMap KWalletD::mapList(
int handle,
const QString &folder,
const QString &appid)
1251 KWallet::Backend *backend = getWallet(appid, handle);
1253 backend->setFolder(folder);
1255 for (KWallet::Entry *entry : lst) {
1256 if (entry->type() == KWallet::Wallet::Map) {
1257 rc.insert(entry->key(), entry->map());
1267 KWallet::Backend *b;
1269 if ((b = getWallet(appid, handle))) {
1270 b->setFolder(folder);
1271 KWallet::Entry *e = b->readEntry(key);
1280#if KWALLET_BUILD_DEPRECATED_SINCE(5, 72)
1281QVariantMap KWalletD::readEntryList(
int handle,
const QString &folder,
const QString &key,
const QString &appid)
1283 KWallet::Backend *b;
1285 if ((b = getWallet(appid, handle))) {
1286 b->setFolder(folder);
1288 const auto lst = b->readEntryList(key);
1289 for (KWallet::Entry *entry : lst) {
1290 rc.insert(entry->key(), entry->value());
1295 return QVariantMap();
1299QVariantMap KWalletD::entriesList(
int handle,
const QString &folder,
const QString &appid)
1303 KWallet::Backend *backend = getWallet(appid, handle);
1305 backend->setFolder(folder);
1307 for (KWallet::Entry *entry : lst) {
1308 rc.insert(entry->key(), entry->value());
1317 KWallet::Backend *b;
1319 if ((b = getWallet(appid, handle))) {
1320 b->setFolder(folder);
1321 return b->entryList();
1329 KWallet::Backend *b;
1331 if ((b = getWallet(appid, handle))) {
1332 b->setFolder(folder);
1333 KWallet::Entry *e = b->readEntry(key);
1334 if (e && e->type() == KWallet::Wallet::Password) {
1335 return e->password();
1342#if KWALLET_BUILD_DEPRECATED_SINCE(5, 72)
1343QVariantMap KWalletD::readPasswordList(
int handle,
const QString &folder,
const QString &key,
const QString &appid)
1345 KWallet::Backend *b;
1347 if ((b = getWallet(appid, handle))) {
1348 b->setFolder(folder);
1350 const auto lst = b->readEntryList(key);
1351 for (KWallet::Entry *entry : lst) {
1352 if (entry->type() == KWallet::Wallet::Password) {
1353 rc.insert(entry->key(), entry->password());
1359 return QVariantMap();
1363QVariantMap KWalletD::passwordList(
int handle,
const QString &folder,
const QString &appid)
1367 KWallet::Backend *backend = getWallet(appid, handle);
1369 backend->setFolder(folder);
1371 for (KWallet::Entry *entry : lst) {
1372 if (entry->type() == KWallet::Wallet::Password) {
1373 rc.insert(entry->key(), entry->password());
1383 KWallet::Backend *b;
1385 if ((b = getWallet(appid, handle))) {
1386 b->setFolder(folder);
1390 e.setType(KWallet::Wallet::Map);
1392 initiateSync(handle);
1393 emitFolderUpdated(b->walletName(), folder);
1394 emitEntryUpdated(b->walletName(), folder, key);
1403 KWallet::Backend *b;
1405 if ((b = getWallet(appid, handle))) {
1406 b->setFolder(folder);
1410 e.setType(KWallet::Wallet::Stream);
1412 initiateSync(handle);
1413 emitFolderUpdated(b->walletName(), folder);
1414 emitEntryUpdated(b->walletName(), folder, key);
1423 KWallet::Backend *b;
1425 if ((b = getWallet(appid, handle))) {
1426 b->setFolder(folder);
1430 e.setType(KWallet::Wallet::EntryType(entryType));
1432 initiateSync(handle);
1433 emitFolderUpdated(b->walletName(), folder);
1442 KWallet::Backend *b;
1444 if ((b = getWallet(appid, handle))) {
1445 b->setFolder(folder);
1449 e.setType(KWallet::Wallet::Password);
1451 initiateSync(handle);
1452 emitFolderUpdated(b->walletName(), folder);
1453 emitEntryUpdated(b->walletName(), folder, key);
1462 KWallet::Backend *b;
1464 if ((b = getWallet(appid, handle))) {
1465 if (!b->hasFolder(folder)) {
1466 return KWallet::Wallet::Unknown;
1468 b->setFolder(folder);
1469 if (b->hasEntry(key)) {
1470 return b->readEntry(key)->type();
1474 return KWallet::Wallet::Unknown;
1479 KWallet::Backend *b;
1481 if ((b = getWallet(appid, handle))) {
1482 if (!b->hasFolder(folder)) {
1485 b->setFolder(folder);
1486 return b->hasEntry(key);
1492int KWalletD::removeEntry(
int handle,
const QString &folder,
const QString &key,
const QString &appid)
1494 KWallet::Backend *b;
1496 if ((b = getWallet(appid, handle))) {
1497 if (!b->hasFolder(folder)) {
1500 b->setFolder(folder);
1501 bool rc = b->removeEntry(key);
1502 initiateSync(handle);
1503 emitFolderUpdated(b->walletName(), folder);
1504 emitEntryDeleted(b->walletName(), folder, key);
1511void KWalletD::slotServiceOwnerChanged(
const QString &name,
const QString &oldOwner,
const QString &newOwner)
1514 qCDebug(KWALLETD_LOG) <<
"slotServiceOwnerChanged " <<
name <<
", " << oldOwner <<
", " << newOwner;
1525 KWallet::Backend *b =
nullptr;
1528 for (
const KWalletAppHandlePair &s : sessremove) {
1529 b = getWallet(s.first, s.second);
1532 internalClose(b, s.second,
false);
1537 for (
const KWalletAppHandlePair &s : sessremove) {
1538 _sessions.removeSession(s.first, service, s.second);
1543 for (tit = _transactions.
begin(); tit != _transactions.
end(); ++tit) {
1544 if ((*tit)->tType == KWalletTransaction::Open && (*tit)->service == oldOwner) {
1553 if (_curtrans && _curtrans->tType == KWalletTransaction::Open && _curtrans->service == oldOwner) {
1554 qCDebug(KWALLETD_LOG) <<
"Cancelling current transaction!";
1555 _curtrans->cancelled =
true;
1560KWallet::Backend *KWalletD::getWallet(
const QString &appid,
int handle)
1566 KWallet::Backend *w = _wallets.
value(handle);
1569 if (_sessions.hasSession(appid, handle)) {
1573 _closeTimers.resetTimer(handle, _idleTime);
1579 if (++_failed > 5) {
1587void KWalletD::notifyFailures()
1589 if (!_showingFailureNotify) {
1590 _showingFailureNotify =
true;
1592 i18n(
"There have been repeated failed attempts to gain access to a wallet. An application may be misbehaving."),
1593 i18n(
"KDE Wallet Service"));
1594 _showingFailureNotify =
false;
1598void KWalletD::doCloseSignals(
int handle,
const QString &wallet)
1600 Q_EMIT walletClosed(handle);
1601 Q_EMIT walletClosedId(handle);
1603 Q_EMIT walletClosed(wallet);
1605 Q_EMIT allWalletsClosed();
1611 KWallet::Backend *b;
1613 if ((b = getWallet(appid, handle))) {
1614 b->setFolder(folder);
1615 int rc = b->renameEntry(oldName, newName);
1616 initiateSync(handle);
1617 emitFolderUpdated(b->walletName(), folder);
1618 emitEntryRenamed(b->walletName(), folder, oldName, newName);
1625int KWalletD::renameWallet(
const QString &oldName,
const QString &newName)
1627 const QPair<int, KWallet::Backend *> walletInfo = findWallet(oldName);
1628 return walletInfo.second->renameWallet(newName);
1633 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1634 return _sessions.getApplications(walletInfo.first);
1637bool KWalletD::disconnectApplication(
const QString &wallet,
const QString &application)
1639 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1640 int handle = walletInfo.first;
1641 KWallet::Backend *backend = walletInfo.second;
1643 if (handle != -1 && _sessions.hasSession(application, handle)) {
1644 int removed = _sessions.removeAllSessions(application, handle);
1646 for (
int i = 0; i < removed; ++i) {
1649 internalClose(backend, handle,
false);
1651 Q_EMIT applicationDisconnected(wallet, application);
1658void KWalletD::emitFolderUpdated(
const QString &wallet,
const QString &folder)
1660 Q_EMIT folderUpdated(wallet, folder);
1665 Q_EMIT entryUpdated(wallet, folder, key);
1670 Q_EMIT entryRenamed(wallet, folder, oldName, newName);
1675 Q_EMIT entryDeleted(wallet, folder, key);
1678void KWalletD::emitWalletListDirty()
1681 const auto lst = _wallets.
values();
1682 for (
auto i : lst) {
1683 if (!walletsInDisk.
contains(i->walletName())) {
1684 internalClose(i, _wallets.
key(i),
true,
false);
1687 Q_EMIT walletListDirty();
1690void KWalletD::reconfigure()
1692 KConfig cfg(QStringLiteral(
"kwalletrc"));
1694 _firstUse = walletGroup.readEntry(
"First Use",
true);
1695 _enabled = walletGroup.readEntry(
"Enabled",
true);
1696 _launchManager = walletGroup.readEntry(
"Launch Manager",
false);
1697 _leaveOpen = walletGroup.readEntry(
"Leave Open",
true);
1698 bool idleSave = _closeIdle;
1699 _closeIdle = walletGroup.readEntry(
"Close When Idle",
false);
1700 _openPrompt = walletGroup.readEntry(
"Prompt on Open",
false);
1701 int timeSave = _idleTime;
1703 _idleTime = walletGroup.readEntry(
"Idle Timeout", 10) * 60 * 1000;
1705 if (walletGroup.readEntry(
"Close on Screensaver",
false)) {
1712 if (screensaver && screensaver->isValid()) {
1713 screensaver->disconnect(SIGNAL(ActiveChanged(
bool)),
this, SLOT(screenSaverChanged(
bool)));
1721 if (_idleTime != timeSave) {
1722 Wallets::const_iterator it = _wallets.
constBegin();
1723 const Wallets::const_iterator
end = _wallets.
constEnd();
1724 for (; it !=
end; ++it) {
1725 _closeTimers.resetTimer(it.key(), _idleTime);
1730 Wallets::const_iterator it = _wallets.
constBegin();
1731 const Wallets::const_iterator
end = _wallets.
constEnd();
1732 for (; it !=
end; ++it) {
1733 _closeTimers.addTimer(it.key(), _idleTime);
1737 _closeTimers.clear();
1741 _implicitAllowMap.
clear();
1743 QStringList entries = autoAllowGroup.entryMap().keys();
1745 _implicitAllowMap[*i] = autoAllowGroup.readEntry(*i,
QStringList());
1749 _implicitDenyMap.
clear();
1751 entries = autoDenyGroup.entryMap().keys();
1753 _implicitDenyMap[*i] = autoDenyGroup.readEntry(*i,
QStringList());
1759 Wallets::const_iterator it = _wallets.
constBegin();
1760 internalClose(it.value(), it.key(),
true);
1766bool KWalletD::isEnabled()
const
1771bool KWalletD::folderDoesNotExist(
const QString &wallet,
const QString &folder)
1773 if (!wallets().contains(wallet)) {
1777 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1778 if (walletInfo.second) {
1779 return walletInfo.second->folderDoesNotExist(folder);
1782 KWallet::Backend *b =
new KWallet::Backend(wallet);
1784 bool rc = b->folderDoesNotExist(folder);
1791 if (!wallets().contains(wallet)) {
1795 const QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1796 if (walletInfo.second) {
1797 return walletInfo.second->entryDoesNotExist(folder, key);
1800 KWallet::Backend *b =
new KWallet::Backend(wallet);
1802 bool rc = b->entryDoesNotExist(folder, key);
1807bool KWalletD::implicitAllow(
const QString &wallet,
const QString &app)
1809 return _implicitAllowMap[wallet].
contains(app);
1812bool KWalletD::implicitDeny(
const QString &wallet,
const QString &app)
1814 return _implicitDenyMap[wallet].
contains(app);
1817void KWalletD::timedOutClose(
int id)
1819 KWallet::Backend *w = _wallets.
value(
id);
1821 internalClose(w,
id,
true);
1825void KWalletD::closeAllWallets()
1827 Wallets walletsCopy = _wallets;
1829 Wallets::const_iterator it = walletsCopy.
constBegin();
1830 const Wallets::const_iterator
end = walletsCopy.constEnd();
1831 for (; it !=
end; ++it) {
1832 internalClose(it.value(), it.key(),
true);
1835 walletsCopy.clear();
1841QString KWalletD::networkWallet()
1846QString KWalletD::localWallet()
1851void KWalletD::screenSaverChanged(
bool s)
1858void KWalletD::activatePasswordDialog()
1860 checkActiveDialog();
1863int KWalletD::pamOpen(
const QString &wallet,
const QByteArray &passwordHash,
int sessionTimeout)
1869 bool brandNew =
false;
1872 QPair<int, KWallet::Backend *> walletInfo = findWallet(wallet);
1873 int rc = walletInfo.first;
1877 if (_wallets.
count() > 20) {
1881 KWallet::Backend *b =
nullptr;
1884 if (!wallets().contains(wallet)) {
1885 b =
new KWallet::Backend(wallet);
1886 b->setCipherType(KWallet::BACKEND_CIPHER_BLOWFISH);
1889 b =
new KWallet::Backend(wallet);
1892 int openrc = b->openPreHashed(passwordHash);
1893 if (openrc != 0 || !b->isOpen()) {
1899 int handle = generateHandle();
1900 _wallets.
insert(handle, b);
1901 _syncTimers.addTimer(handle, _syncTime);
1906 if (sessionTimeout > 0) {
1907 _closeTimers.addTimer(handle, sessionTimeout);
1908 }
else if (_closeIdle) {
1909 _closeTimers.addTimer(handle, _idleTime);
1912 Q_EMIT walletCreated(wallet);
1914 Q_EMIT walletOpened(wallet);
1916 if (_wallets.
count() == 1 && _launchManager) {
1917 startManagerForKwalletd();
1925#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...)
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)