00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "kbetterthankdialogbase.h"
00024
#include "kwalletwizard.h"
00025
#include "kwalletd.h"
00026
#include "ktimeout.h"
00027
00028
#include <dcopclient.h>
00029
#include <dcopref.h>
00030
#include <kactivelabel.h>
00031
#include <kapplication.h>
00032
#include <kconfig.h>
00033
#include <kdebug.h>
00034
#include <kdirwatch.h>
00035
#include <kglobal.h>
00036
#include <klocale.h>
00037
#include <kmessagebox.h>
00038
#include <kpassdlg.h>
00039
#include <kstandarddirs.h>
00040
#include <kwalletentry.h>
00041
#include <kwin.h>
00042
00043
#include <qdir.h>
00044
#include <qlabel.h>
00045
#include <qlayout.h>
00046
#include <qpushbutton.h>
00047
#include <qregexp.h>
00048
#include <qstylesheet.h>
00049
#include <qvbox.h>
00050
00051
#include <assert.h>
00052
00053
#ifdef Q_WS_X11
00054
#include <X11/Xlib.h>
00055
#endif
00056
00057
extern "C" {
00058 KDE_EXPORT KDEDModule *create_kwalletd(
const QCString &name) {
00059
return new KWalletD(name);
00060 }
00061 }
00062
00063
00064
class KWalletTransaction {
00065
public:
00066 KWalletTransaction() {
00067 tType = Unknown;
00068 transaction = 0L;
00069 client = 0L;
00070 }
00071
00072 ~KWalletTransaction() {
00073
00074 transaction = 0L;
00075 client = 0L;
00076 }
00077
00078
enum Type { Unknown, Open, ChangePassword, OpenFail };
00079
DCOPClient *client;
00080 DCOPClientTransaction *transaction;
00081 Type tType;
00082
QCString rawappid, returnObject;
00083
QCString appid;
00084 uint wId;
00085
QString wallet;
00086 };
00087
00088
00089 KWalletD::KWalletD(
const QCString &name)
00090 : KDEDModule(
name), _failed(0) {
00091 srand(time(0));
00092 _showingFailureNotify =
false;
00093 _transactions.setAutoDelete(
true);
00094 _timeouts =
new KTimeout(17);
00095 _closeIdle =
false;
00096 _idleTime = 0;
00097 connect(_timeouts, SIGNAL(timedOut(
int)),
this, SLOT(timedOut(
int)));
00098 reconfigure();
00099
KGlobal::dirs()->
addResourceType(
"kwallet",
"share/apps/kwallet");
00100 connect(KApplication::dcopClient(),
00101 SIGNAL(applicationRemoved(
const QCString&)),
00102
this,
00103 SLOT(slotAppUnregistered(
const QCString&)));
00104 _dw =
new KDirWatch(
this,
"KWallet Directory Watcher");
00105 _dw->addDir(KGlobal::dirs()->saveLocation(
"kwallet"));
00106 _dw->startScan(
true);
00107 connect(_dw, SIGNAL(dirty(
const QString&)),
this, SLOT(emitWalletListDirty()));
00108 }
00109
00110
00111 KWalletD::~KWalletD() {
00112
delete _timeouts;
00113 _timeouts = 0;
00114
00115 closeAllWallets();
00116 _transactions.clear();
00117 }
00118
00119
00120
int KWalletD::generateHandle() {
00121
int rc;
00122
00123
00124
do {
00125 rc = rand();
00126 }
while (_wallets.find(rc) || rc == 0);
00127
00128
return rc;
00129 }
00130
00131
00132
void KWalletD::processTransactions() {
00133
static bool processing =
false;
00134
00135
if (processing) {
00136
return;
00137 }
00138
00139 processing =
true;
00140
00141
00142 KWalletTransaction *xact;
00143
while (!_transactions.isEmpty()) {
00144 xact = _transactions.first();
00145
QCString replyType;
00146
int res;
00147
00148 assert(xact->tType != KWalletTransaction::Unknown);
00149
00150
switch (xact->tType) {
00151
case KWalletTransaction::Open:
00152 res = doTransactionOpen(xact->appid, xact->wallet, xact->wId);
00153 replyType =
"int";
00154
if (!xact->returnObject.isEmpty()) {
00155
DCOPRef(xact->rawappid, xact->returnObject).send(
"walletOpenResult", res);
00156 }
00157
00158
00159
00160
00161
if (res < 0) {
00162
QPtrListIterator<KWalletTransaction> it(_transactions);
00163 KWalletTransaction *x;
00164
while ((x = it.current()) && x != xact) {
00165 ++it;
00166 }
00167
if (x) {
00168 ++it;
00169 }
00170
while ((x = it.current())) {
00171
if (xact->appid == x->appid && x->tType == KWalletTransaction::Open && x->wallet == xact->wallet && x->wId == xact->wId) {
00172 x->tType = KWalletTransaction::OpenFail;
00173 }
00174 ++it;
00175 }
00176 }
00177
break;
00178
case KWalletTransaction::OpenFail:
00179 res = -1;
00180 replyType =
"int";
00181
if (!xact->returnObject.isEmpty()) {
00182
DCOPRef(xact->rawappid, xact->returnObject).send(
"walletOpenResult", res);
00183 }
00184
break;
00185
case KWalletTransaction::ChangePassword:
00186 doTransactionChangePassword(xact->appid, xact->wallet, xact->wId);
00187
00188
default:
00189 _transactions.removeRef(xact);
00190
continue;
00191 }
00192
00193
if (xact->returnObject.isEmpty() && xact->tType != KWalletTransaction::ChangePassword) {
00194
QByteArray replyData;
00195
QDataStream stream(replyData, IO_WriteOnly);
00196 stream << res;
00197 xact->client->endTransaction(xact->transaction, replyType, replyData);
00198 }
00199 _transactions.removeRef(xact);
00200 }
00201
00202 processing =
false;
00203 }
00204
00205
00206
void KWalletD::openAsynchronous(
const QString& wallet,
const QCString& returnObject, uint wId) {
00207
DCOPClient *dc = callingDcopClient();
00208
if (!dc) {
00209
return;
00210 }
00211
00212
QCString appid = dc->
senderId();
00213
if (!_enabled ||
00214 !
QRegExp(
"^[A-Za-z0-9]+[A-Za-z0-9\\s\\-_]*$").exactMatch(wallet)) {
00215
DCOPRef(appid, returnObject).send(
"walletOpenResult", -1);
00216
return;
00217 }
00218
00219
QCString peerName = friendlyDCOPPeerName();
00220
00221 KWalletTransaction *xact =
new KWalletTransaction;
00222
00223 xact->appid = peerName;
00224 xact->rawappid = appid;
00225 xact->client = callingDcopClient();
00226 xact->wallet = wallet;
00227 xact->wId = wId;
00228 xact->tType = KWalletTransaction::Open;
00229 xact->returnObject = returnObject;
00230 _transactions.append(xact);
00231
00232
DCOPRef(appid, returnObject).send(
"walletOpenResult", 0);
00233
00234 QTimer::singleShot(0,
this, SLOT(processTransactions()));
00235 }
00236
00237
00238
int KWalletD::openPath(
const QString& path, uint wId) {
00239
if (!_enabled) {
00240
return -1;
00241 }
00242
00243
00244
int rc = internalOpen(friendlyDCOPPeerName(), path,
true, wId);
00245
return rc;
00246 }
00247
00248
00249
int KWalletD::open(
const QString& wallet, uint wId) {
00250
if (!_enabled) {
00251
return -1;
00252 }
00253
00254
if (!
QRegExp(
"^[A-Za-z0-9]+[A-Za-z0-9\\s\\-_]*$").exactMatch(wallet)) {
00255
return -1;
00256 }
00257
00258
QCString appid = friendlyDCOPPeerName();
00259
00260 KWalletTransaction *xact =
new KWalletTransaction;
00261 _transactions.append(xact);
00262
00263
if (_transactions.count() > 1) {
00264 xact->appid = appid;
00265 xact->client = callingDcopClient();
00266 xact->transaction = xact->client->beginTransaction();
00267 xact->wallet = wallet;
00268 xact->wId = wId;
00269 xact->tType = KWalletTransaction::Open;
00270
return 0;
00271 }
00272
00273
int rc = doTransactionOpen(appid, wallet, wId);
00274
00275 _transactions.remove(xact);
00276
00277
if (rc < 0) {
00278
00279
for (KWalletTransaction *x = _transactions.first(); x; x = _transactions.next()) {
00280
if (appid == x->appid && x->tType == KWalletTransaction::Open && x->wallet == wallet && x->wId == wId)
00281 x->tType = KWalletTransaction::OpenFail;
00282 }
00283 }
00284
00285 processTransactions();
00286
00287
return rc;
00288 }
00289
00290
00291
int KWalletD::doTransactionOpen(
const QCString& appid,
const QString& wallet, uint wId) {
00292
if (_firstUse && !wallets().contains(KWallet::Wallet::LocalWallet())) {
00293
00294 KWalletWizard *wiz =
new KWalletWizard(0);
00295
#ifdef Q_WS_X11
00296
XSetTransientForHint(qt_xdisplay(), wiz->winId(), wId);
00297
#endif
00298
int rc = wiz->exec();
00299
if (rc == QDialog::Accepted) {
00300
KConfig cfg(
"kwalletrc");
00301 cfg.
setGroup(
"Wallet");
00302 cfg.
writeEntry(
"First Use",
false);
00303 cfg.
writeEntry(
"Enabled", wiz->_useWallet->isChecked());
00304 cfg.
writeEntry(
"Close When Idle", wiz->_closeIdle->isChecked());
00305 cfg.
writeEntry(
"Use One Wallet", !wiz->_networkWallet->isChecked());
00306 cfg.
sync();
00307 reconfigure();
00308
00309
if (!wiz->_useWallet->isChecked()) {
00310
delete wiz;
00311
return -1;
00312 }
00313
00314
00315 KWallet::Backend *b =
new KWallet::Backend(KWallet::Wallet::LocalWallet());
00316
QByteArray p;
00317 p.duplicate(wiz->_pass1->text().utf8(), wiz->_pass1->text().length());
00318 b->open(p);
00319 b->createFolder(KWallet::Wallet::PasswordFolder());
00320 b->createFolder(KWallet::Wallet::FormDataFolder());
00321 b->close(p);
00322 p.fill(0);
00323
delete b;
00324
delete wiz;
00325 }
else {
00326
delete wiz;
00327
return -1;
00328 }
00329 }
else if (_firstUse) {
00330
KConfig cfg(
"kwalletrc");
00331 _firstUse =
false;
00332 cfg.
setGroup(
"Wallet");
00333 cfg.
writeEntry(
"First Use",
false);
00334 cfg.
sync();
00335 }
00336
00337
int rc = internalOpen(appid, wallet,
false, wId);
00338
return rc;
00339 }
00340
00341
00342
int KWalletD::internalOpen(
const QCString& appid,
const QString& wallet,
bool isPath, WId w) {
00343
int rc = -1;
00344
bool brandNew =
false;
00345
00346
QCString thisApp;
00347
if (appid.isEmpty()) {
00348 thisApp =
"KDE System";
00349 }
else {
00350 thisApp = appid;
00351 }
00352
00353
if (implicitDeny(wallet, thisApp)) {
00354
return -1;
00355 }
00356
00357
for (
QIntDictIterator<KWallet::Backend> i(_wallets); i.current(); ++i) {
00358
if (i.current()->walletName() == wallet) {
00359 rc = i.currentKey();
00360
break;
00361 }
00362 }
00363
00364
if (rc == -1) {
00365
if (_wallets.count() > 20) {
00366
kdDebug() <<
"Too many wallets open." <<
endl;
00367
return -1;
00368 }
00369
00370 KWallet::Backend *b =
new KWallet::Backend(wallet, isPath);
00371
KPasswordDialog *kpd = 0L;
00372
bool emptyPass =
false;
00373
if ((isPath && QFile::exists(wallet)) || (!isPath && KWallet::Backend::exists(wallet))) {
00374
int pwless = b->open(
QByteArray());
00375
if (0 != pwless || !b->isOpen()) {
00376
if (pwless == 0) {
00377
00378
delete b;
00379 b =
new KWallet::Backend(wallet, isPath);
00380 }
00381 kpd =
new KPasswordDialog(KPasswordDialog::Password,
false, 0);
00382
if (appid.isEmpty()) {
00383 kpd->
setPrompt(i18n(
"<qt>KDE has requested to open the wallet '<b>%1</b>'. Please enter the password for this wallet below.").arg(QStyleSheet::escape(wallet)));
00384 }
else {
00385 kpd->
setPrompt(i18n(
"<qt>The application '<b>%1</b>' has requested to open the wallet '<b>%2</b>'. Please enter the password for this wallet below.").arg(QStyleSheet::escape(appid)).arg(QStyleSheet::escape(wallet)));
00386 }
00387 brandNew =
false;
00388 kpd->
setButtonOK(
KGuiItem(i18n(
"&Open"),
"fileopen"));
00389 }
else {
00390 emptyPass =
true;
00391 }
00392 }
else if (wallet == KWallet::Wallet::LocalWallet() ||
00393 wallet == KWallet::Wallet::NetworkWallet()) {
00394
00395 kpd =
new KPasswordDialog(KPasswordDialog::NewPassword,
false, 0);
00396
if (appid.isEmpty()) {
00397 kpd->
setPrompt(i18n(
"KDE has requested to open the wallet. This is used to store sensitive data in a secure fashion. Please enter a password to use with this wallet or click cancel to deny the application's request."));
00398 }
else {
00399 kpd->
setPrompt(i18n(
"<qt>The application '<b>%1</b>' has requested to open the KDE wallet. This is used to store sensitive data in a secure fashion. Please enter a password to use with this wallet or click cancel to deny the application's request.").arg(QStyleSheet::escape(appid)));
00400 }
00401 brandNew =
true;
00402 kpd->
setButtonOK(
KGuiItem(i18n(
"&Open"),
"fileopen"));
00403 }
else {
00404 kpd =
new KPasswordDialog(KPasswordDialog::NewPassword,
false, 0);
00405
if (appid.length() == 0) {
00406 kpd->
setPrompt(i18n(
"<qt>KDE has requested to create a new wallet named '<b>%1</b>'. Please choose a password for this wallet, or cancel to deny the application's request.").arg(QStyleSheet::escape(wallet)));
00407 }
else {
00408 kpd->
setPrompt(i18n(
"<qt>The application '<b>%1</b>' has requested to create a new wallet named '<b>%2</b>'. Please choose a password for this wallet, or cancel to deny the application's request.").arg(QStyleSheet::escape(appid)).arg(QStyleSheet::escape(wallet)));
00409 }
00410 brandNew =
true;
00411 kpd->
setButtonOK(
KGuiItem(i18n(
"C&reate"),
"filenew"));
00412 }
00413
00414
if (kpd) {
00415 kpd->
setCaption(i18n(
"KDE Wallet Service"));
00416 kpd->
setAllowEmptyPasswords(
true);
00417 }
00418
00419
const char *p = 0L;
00420
while (!b->isOpen()) {
00421
#ifdef Q_WS_X11
00422
XSetTransientForHint(qt_xdisplay(), kpd->winId(), w);
00423
#endif
00424
KWin::setState( kpd->winId(),
NET::KeepAbove );
00425 KWin::setOnAllDesktops(kpd->winId(),
true);
00426
if (kpd->exec() == KDialog::Accepted) {
00427 p = kpd->
password();
00428
int rc = b->open(
QByteArray().duplicate(p, strlen(p)));
00429
if (!b->isOpen()) {
00430 kpd->
setPrompt(i18n(
"<qt>Error opening the wallet '<b>%1</b>'. Please try again.<br>(Error code %2: %3)").arg(QStyleSheet::escape(wallet)).arg(rc).arg(KWallet::Backend::openRCToString(rc)));
00431 kpd->
clearPassword();
00432 }
00433 }
else {
00434
break;
00435 }
00436 }
00437
00438
if (!emptyPass && (!p || !b->isOpen())) {
00439
delete b;
00440
delete kpd;
00441
return -1;
00442 }
00443
00444
if (emptyPass && _openPrompt && !isAuthorizedApp(appid, wallet, w)) {
00445
delete b;
00446
delete kpd;
00447
return -1;
00448 }
00449
00450 _wallets.insert(rc = generateHandle(), b);
00451
if (emptyPass) {
00452 _passwords[wallet] =
"";
00453 }
else {
00454 _passwords[wallet] = p;
00455 }
00456 _handles[appid].append(rc);
00457
00458
delete kpd;
00459
00460
if (brandNew) {
00461 createFolder(rc, KWallet::Wallet::PasswordFolder());
00462 createFolder(rc, KWallet::Wallet::FormDataFolder());
00463 }
00464
00465 b->ref();
00466
if (_closeIdle && _timeouts) {
00467 _timeouts->addTimer(rc, _idleTime);
00468 }
00469
QByteArray data;
00470
QDataStream ds(data, IO_WriteOnly);
00471 ds << wallet;
00472
if (brandNew) {
00473 emitDCOPSignal(
"walletCreated(QString)", data);
00474 }
00475 emitDCOPSignal(
"walletOpened(QString)", data);
00476
if (_wallets.count() == 1 && _launchManager) {
00477
KApplication::startServiceByDesktopName(
"kwalletmanager-kwalletd");
00478 }
00479 }
else {
00480
if (!_handles[appid].contains(rc) && _openPrompt && !isAuthorizedApp(appid, wallet, w)) {
00481
return -1;
00482 }
00483 _handles[appid].append(rc);
00484 _wallets.find(rc)->ref();
00485 }
00486
00487
return rc;
00488 }
00489
00490
00491
bool KWalletD::isAuthorizedApp(
const QCString& appid,
const QString& wallet, WId w) {
00492
int response = 0;
00493
00494
QCString thisApp;
00495
if (appid.isEmpty()) {
00496 thisApp =
"KDE System";
00497 }
else {
00498 thisApp = appid;
00499 }
00500
00501
if (!implicitAllow(wallet, thisApp)) {
00502 KBetterThanKDialogBase *dialog =
new KBetterThanKDialogBase;
00503
if (appid.isEmpty()) {
00504 dialog->setLabel(i18n(
"<qt>KDE has requested access to the open wallet '<b>%1</b>'.").arg(QStyleSheet::escape(wallet)));
00505 }
else {
00506 dialog->setLabel(i18n(
"<qt>The application '<b>%1</b>' has requested access to the open wallet '<b>%2</b>'.").arg(QStyleSheet::escape(
QString(appid))).arg(QStyleSheet::escape(wallet)));
00507 }
00508
#ifdef Q_WS_X11
00509
XSetTransientForHint(qt_xdisplay(), dialog->winId(), w);
00510
#endif
00511
KWin::setState(dialog->winId(),
NET::KeepAbove);
00512 KWin::setOnAllDesktops(dialog->winId(),
true);
00513
00514 response = dialog->exec();
00515
delete dialog;
00516 }
00517
00518
if (response == 0 || response == 1) {
00519
if (response == 1) {
00520
KConfig cfg(
"kwalletrc");
00521 cfg.
setGroup(
"Auto Allow");
00522
QStringList apps = cfg.
readListEntry(wallet);
00523
if (!apps.contains(thisApp)) {
00524 apps += thisApp;
00525 _implicitAllowMap[wallet] += thisApp;
00526 cfg.
writeEntry(wallet, apps);
00527 cfg.
sync();
00528 }
00529 }
00530 }
else if (response == 3) {
00531
KConfig cfg(
"kwalletrc");
00532 cfg.
setGroup(
"Auto Deny");
00533
QStringList apps = cfg.
readListEntry(wallet);
00534
if (!apps.contains(thisApp)) {
00535 apps += thisApp;
00536 _implicitDenyMap[wallet] += thisApp;
00537 cfg.
writeEntry(wallet, apps);
00538 cfg.
sync();
00539 }
00540
return false;
00541 }
else {
00542
return false;
00543 }
00544
return true;
00545 }
00546
00547
00548
int KWalletD::deleteWallet(
const QString& wallet) {
00549
QString path =
KGlobal::dirs()->
saveLocation(
"kwallet") + QDir::separator() + wallet +
".kwl";
00550
00551
if (QFile::exists(path)) {
00552
close(wallet,
true);
00553 QFile::remove(path);
00554
QByteArray data;
00555
QDataStream ds(data, IO_WriteOnly);
00556 ds << wallet;
00557 emitDCOPSignal(
"walletDeleted(QString)", data);
00558
return 0;
00559 }
00560
00561
return -1;
00562 }
00563
00564
00565
void KWalletD::changePassword(
const QString& wallet, uint wId) {
00566
QCString appid = friendlyDCOPPeerName();
00567
00568 KWalletTransaction *xact =
new KWalletTransaction;
00569
00570 xact->appid = appid;
00571 xact->client = callingDcopClient();
00572 xact->wallet = wallet;
00573 xact->wId = wId;
00574 xact->tType = KWalletTransaction::ChangePassword;
00575
00576 _transactions.append(xact);
00577
00578 QTimer::singleShot(0,
this, SLOT(processTransactions()));
00579 }
00580
00581
00582
void KWalletD::doTransactionChangePassword(
const QCString& appid,
const QString& wallet, uint wId) {
00583
QIntDictIterator<KWallet::Backend> it(_wallets);
00584 KWallet::Backend *w = 0L;
00585
int handle = -1;
00586
bool reclose =
false;
00587
00588
for (; it.current(); ++it) {
00589
if (it.current()->walletName() == wallet) {
00590
break;
00591 }
00592 }
00593
00594
if (!it.current()) {
00595 handle = doTransactionOpen(appid, wallet, wId);
00596
if (-1 == handle) {
00597
KMessageBox::sorryWId(wId, i18n(
"Unable to open wallet. The wallet must be opened in order to change the password."), i18n(
"KDE Wallet Service"));
00598
return;
00599 }
00600
00601 w = _wallets.find(handle);
00602 reclose =
true;
00603 }
else {
00604 handle = it.currentKey();
00605 w = it.current();
00606 }
00607
00608 assert(w);
00609
00610 KPasswordDialog *kpd;
00611 kpd =
new KPasswordDialog(KPasswordDialog::NewPassword,
false, 0);
00612 kpd->
setPrompt(i18n(
"<qt>Please choose a new password for the wallet '<b>%1</b>'.").arg(QStyleSheet::escape(wallet)));
00613 kpd->
setCaption(i18n(
"KDE Wallet Service"));
00614 kpd->
setAllowEmptyPasswords(
true);
00615
#ifdef Q_WS_X11
00616
XSetTransientForHint(qt_xdisplay(), kpd->winId(), wId);
00617
#endif
00618
if (kpd->exec() == KDialog::Accepted) {
00619
const char *p = kpd->
password();
00620
if (p) {
00621 _passwords[wallet] = p;
00622
QByteArray pa;
00623 pa.duplicate(p, strlen(p));
00624
int rc = w->close(pa);
00625
if (rc < 0) {
00626
KMessageBox::sorryWId(wId, i18n(
"Error re-encrypting the wallet. Password was not changed."), i18n(
"KDE Wallet Service"));
00627 reclose =
true;
00628 }
else {
00629 rc = w->open(pa);
00630
if (rc < 0) {
00631
KMessageBox::sorryWId(wId, i18n(
"Error reopening the wallet. Data may be lost."), i18n(
"KDE Wallet Service"));
00632 reclose =
true;
00633 }
00634 }
00635 }
00636 }
00637
00638
delete kpd;
00639
00640
if (reclose) {
00641
close(handle,
true);
00642 }
00643 }
00644
00645
00646
int KWalletD::close(
const QString& wallet,
bool force) {
00647
int handle = -1;
00648 KWallet::Backend *w = 0L;
00649
00650
for (
QIntDictIterator<KWallet::Backend> it(_wallets);
00651 it.current();
00652 ++it) {
00653
if (it.current()->walletName() == wallet) {
00654 handle = it.currentKey();
00655 w = it.current();
00656
break;
00657 }
00658 }
00659
00660
return closeWallet(w, handle, force);
00661 }
00662
00663
00664
int KWalletD::closeWallet(KWallet::Backend *w,
int handle,
bool force) {
00665
if (w) {
00666
const QString& wallet = w->walletName();
00667 assert(_passwords.contains(wallet));
00668
if (w->refCount() == 0 || force) {
00669 invalidateHandle(handle);
00670
if (_closeIdle && _timeouts) {
00671 _timeouts->removeTimer(handle);
00672 }
00673 _wallets.remove(handle);
00674
if (_passwords.contains(wallet)) {
00675 w->close(
QByteArray().duplicate(_passwords[wallet].data(), _passwords[wallet].length()));
00676 _passwords[wallet].fill(0);
00677 _passwords.remove(wallet);
00678 }
00679 doCloseSignals(handle, wallet);
00680
delete w;
00681
return 0;
00682 }
00683
return 1;
00684 }
00685
00686
return -1;
00687 }
00688
00689
00690
int KWalletD::close(
int handle,
bool force) {
00691
QCString appid = friendlyDCOPPeerName();
00692 KWallet::Backend *w = _wallets.find(handle);
00693
bool contains =
false;
00694
00695
if (w) {
00696
if (_handles.contains(appid)) {
00697
if (_handles[appid].contains(handle)) {
00698
00699 _handles[appid].remove(_handles[appid].
find(handle));
00700 contains =
true;
00701
if (_handles[appid].isEmpty()) {
00702 _handles.remove(appid);
00703 }
00704 }
00705 }
00706
00707
00708
if ((contains && w->deref() == 0 && !_leaveOpen) || force) {
00709
if (_closeIdle && _timeouts) {
00710 _timeouts->removeTimer(handle);
00711 }
00712 _wallets.remove(handle);
00713
if (force) {
00714 invalidateHandle(handle);
00715 }
00716
if (_passwords.contains(w->walletName())) {
00717 w->close(
QByteArray().duplicate(_passwords[w->walletName()].data(), _passwords[w->walletName()].length()));
00718 _passwords[w->walletName()].fill(0);
00719 _passwords.remove(w->walletName());
00720 }
00721 doCloseSignals(handle, w->walletName());
00722
delete w;
00723
return 0;
00724 }
00725
return 1;
00726 }
00727
00728
return -1;
00729 }
00730
00731
00732
bool KWalletD::isOpen(
const QString& wallet)
const {
00733
for (
QIntDictIterator<KWallet::Backend> it(_wallets);
00734 it.current();
00735 ++it) {
00736
if (it.current()->walletName() == wallet) {
00737
return true;
00738 }
00739 }
00740
return false;
00741 }
00742
00743
00744
bool KWalletD::isOpen(
int handle) {
00745
if (handle == 0) {
00746
return false;
00747 }
00748
00749 KWallet::Backend *rc = _wallets.find(handle);
00750
00751
if (rc == 0 && ++_failed > 5) {
00752 _failed = 0;
00753 QTimer::singleShot(0,
this, SLOT(notifyFailures()));
00754 }
else if (rc != 0) {
00755 _failed = 0;
00756 }
00757
00758
return rc != 0;
00759 }
00760
00761
00762
QStringList KWalletD::wallets()
const {
00763
QString path =
KGlobal::dirs()->
saveLocation(
"kwallet");
00764
QDir dir(path,
"*.kwl");
00765
QStringList rc;
00766
00767 dir.setFilter(QDir::Files | QDir::NoSymLinks);
00768
00769
const QFileInfoList *list = dir.entryInfoList();
00770 QFileInfoListIterator it(*list);
00771
QFileInfo *fi;
00772
while ((fi = it.current()) != 0L) {
00773
QString fn = fi->fileName();
00774
if (fn.endsWith(
".kwl")) {
00775 fn.truncate(fn.length()-4);
00776 }
00777 rc += fn;
00778 ++it;
00779 }
00780
return rc;
00781 }
00782
00783
00784
void KWalletD::sync(
int handle) {
00785 KWallet::Backend *b;
00786
00787
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00788
QByteArray p;
00789
QString wallet = b->walletName();
00790 p.duplicate(_passwords[wallet].data(), _passwords[wallet].length());
00791 b->sync(p);
00792 p.fill(0);
00793 }
00794 }
00795
00796
00797
QStringList KWalletD::folderList(
int handle) {
00798 KWallet::Backend *b;
00799
00800
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00801
return b->folderList();
00802 }
00803
00804
return QStringList();
00805 }
00806
00807
00808
bool KWalletD::hasFolder(
int handle,
const QString& f) {
00809 KWallet::Backend *b;
00810
00811
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00812
return b->hasFolder(f);
00813 }
00814
00815
return false;
00816 }
00817
00818
00819
bool KWalletD::removeFolder(
int handle,
const QString& f) {
00820 KWallet::Backend *b;
00821
00822
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00823
bool rc = b->removeFolder(f);
00824
QByteArray data;
00825
QDataStream ds(data, IO_WriteOnly);
00826 ds << b->walletName();
00827 emitDCOPSignal(
"folderListUpdated(QString)", data);
00828
return rc;
00829 }
00830
00831
return false;
00832 }
00833
00834
00835
bool KWalletD::createFolder(
int handle,
const QString& f) {
00836 KWallet::Backend *b;
00837
00838
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00839
bool rc = b->createFolder(f);
00840
QByteArray data;
00841
QDataStream ds(data, IO_WriteOnly);
00842 ds << b->walletName();
00843 emitDCOPSignal(
"folderListUpdated(QString)", data);
00844
return rc;
00845 }
00846
00847
return false;
00848 }
00849
00850
00851
QByteArray KWalletD::readMap(
int handle,
const QString& folder,
const QString& key) {
00852 KWallet::Backend *b;
00853
00854
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00855 b->setFolder(folder);
00856 KWallet::Entry *e = b->readEntry(key);
00857
if (e && e->type() == KWallet::Wallet::Map) {
00858
return e->map();
00859 }
00860 }
00861
00862
return QByteArray();
00863 }
00864
00865
00866
QMap<QString,QByteArray> KWalletD::readMapList(
int handle,
const QString& folder,
const QString& key) {
00867 KWallet::Backend *b;
00868
00869
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00870 b->setFolder(folder);
00871
QPtrList<KWallet::Entry> e = b->readEntryList(key);
00872
QMap<QString, QByteArray> rc;
00873
QPtrListIterator<KWallet::Entry> it(e);
00874 KWallet::Entry *entry;
00875
while ((entry = it.current())) {
00876
if (entry->type() == KWallet::Wallet::Map) {
00877 rc.insert(entry->key(), entry->map());
00878 }
00879 ++it;
00880 }
00881
return rc;
00882 }
00883
00884
return QMap<QString, QByteArray>();
00885 }
00886
00887
00888
QByteArray KWalletD::readEntry(
int handle,
const QString& folder,
const QString& key) {
00889 KWallet::Backend *b;
00890
00891
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00892 b->setFolder(folder);
00893 KWallet::Entry *e = b->readEntry(key);
00894
if (e) {
00895
return e->value();
00896 }
00897 }
00898
00899
return QByteArray();
00900 }
00901
00902
00903
QMap<QString, QByteArray> KWalletD::readEntryList(
int handle,
const QString& folder,
const QString& key) {
00904 KWallet::Backend *b;
00905
00906
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00907 b->setFolder(folder);
00908
QPtrList<KWallet::Entry> e = b->readEntryList(key);
00909
QMap<QString, QByteArray> rc;
00910
QPtrListIterator<KWallet::Entry> it(e);
00911 KWallet::Entry *entry;
00912
while ((entry = it.current())) {
00913 rc.insert(entry->key(), entry->value());
00914 ++it;
00915 }
00916
return rc;
00917 }
00918
00919
return QMap<QString, QByteArray>();
00920 }
00921
00922
00923
QStringList KWalletD::entryList(
int handle,
const QString& folder) {
00924 KWallet::Backend *b;
00925
00926
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00927 b->setFolder(folder);
00928
return b->entryList();
00929 }
00930
00931
return QStringList();
00932 }
00933
00934
00935
QString KWalletD::readPassword(
int handle,
const QString& folder,
const QString& key) {
00936 KWallet::Backend *b;
00937
00938
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00939 b->setFolder(folder);
00940 KWallet::Entry *e = b->readEntry(key);
00941
if (e && e->type() == KWallet::Wallet::Password) {
00942
return e->password();
00943 }
00944 }
00945
00946
return QString::null;
00947 }
00948
00949
00950
QMap<QString, QString> KWalletD::readPasswordList(
int handle,
const QString& folder,
const QString& key) {
00951 KWallet::Backend *b;
00952
00953
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00954 b->setFolder(folder);
00955
QPtrList<KWallet::Entry> e = b->readEntryList(key);
00956
QMap<QString, QString> rc;
00957
QPtrListIterator<KWallet::Entry> it(e);
00958 KWallet::Entry *entry;
00959
while ((entry = it.current())) {
00960
if (entry->type() == KWallet::Wallet::Password) {
00961 rc.insert(entry->key(), entry->password());
00962 }
00963 ++it;
00964 }
00965
return rc;
00966 }
00967
00968
return QMap<QString, QString>();
00969 }
00970
00971
00972
int KWalletD::writeMap(
int handle,
const QString& folder,
const QString& key,
const QByteArray& value) {
00973 KWallet::Backend *b;
00974
00975
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00976 b->setFolder(folder);
00977 KWallet::Entry e;
00978 e.setKey(key);
00979 e.setValue(value);
00980 e.setType(KWallet::Wallet::Map);
00981 b->writeEntry(&e);
00982 emitFolderUpdated(b->walletName(), folder);
00983
return 0;
00984 }
00985
00986
return -1;
00987 }
00988
00989
00990
int KWalletD::writeEntry(
int handle,
const QString& folder,
const QString& key,
const QByteArray& value,
int entryType) {
00991 KWallet::Backend *b;
00992
00993
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
00994 b->setFolder(folder);
00995 KWallet::Entry e;
00996 e.setKey(key);
00997 e.setValue(value);
00998 e.setType(KWallet::Wallet::EntryType(entryType));
00999 b->writeEntry(&e);
01000 emitFolderUpdated(b->walletName(), folder);
01001
return 0;
01002 }
01003
01004
return -1;
01005 }
01006
01007
01008
int KWalletD::writeEntry(
int handle,
const QString& folder,
const QString& key,
const QByteArray& value) {
01009 KWallet::Backend *b;
01010
01011
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
01012 b->setFolder(folder);
01013 KWallet::Entry e;
01014 e.setKey(key);
01015 e.setValue(value);
01016 e.setType(KWallet::Wallet::Stream);
01017 b->writeEntry(&e);
01018 emitFolderUpdated(b->walletName(), folder);
01019
return 0;
01020 }
01021
01022
return -1;
01023 }
01024
01025
01026
int KWalletD::writePassword(
int handle,
const QString& folder,
const QString& key,
const QString& value) {
01027 KWallet::Backend *b;
01028
01029
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
01030 b->setFolder(folder);
01031 KWallet::Entry e;
01032 e.setKey(key);
01033 e.setValue(value);
01034 e.setType(KWallet::Wallet::Password);
01035 b->writeEntry(&e);
01036 emitFolderUpdated(b->walletName(), folder);
01037
return 0;
01038 }
01039
01040
return -1;
01041 }
01042
01043
01044
int KWalletD::entryType(
int handle,
const QString& folder,
const QString& key) {
01045 KWallet::Backend *b;
01046
01047
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
01048
if (!b->hasFolder(folder)) {
01049
return KWallet::Wallet::Unknown;
01050 }
01051 b->setFolder(folder);
01052
if (b->hasEntry(key)) {
01053
return b->readEntry(key)->type();
01054 }
01055 }
01056
01057
return KWallet::Wallet::Unknown;
01058 }
01059
01060
01061
bool KWalletD::hasEntry(
int handle,
const QString& folder,
const QString& key) {
01062 KWallet::Backend *b;
01063
01064
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
01065
if (!b->hasFolder(folder)) {
01066
return false;
01067 }
01068 b->setFolder(folder);
01069
return b->hasEntry(key);
01070 }
01071
01072
return false;
01073 }
01074
01075
01076
int KWalletD::removeEntry(
int handle,
const QString& folder,
const QString& key) {
01077 KWallet::Backend *b;
01078
01079
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
01080
if (!b->hasFolder(folder)) {
01081
return 0;
01082 }
01083 b->setFolder(folder);
01084
bool rc = b->removeEntry(key);
01085 emitFolderUpdated(b->walletName(), folder);
01086
return rc ? 0 : -3;
01087 }
01088
01089
return -1;
01090 }
01091
01092
01093
void KWalletD::slotAppUnregistered(
const QCString& app) {
01094
if (_handles.contains(app)) {
01095
QValueList<int> l = _handles[app];
01096
for (
QValueList<int>::Iterator i = l.begin(); i != l.end(); i++) {
01097 _handles[app].remove(*i);
01098 KWallet::Backend *w = _wallets.find(*i);
01099
if (w && !_leaveOpen && 0 == w->deref()) {
01100
close(w->walletName(),
true);
01101 }
01102 }
01103 _handles.remove(app);
01104 }
01105 }
01106
01107
01108
void KWalletD::invalidateHandle(
int handle) {
01109
for (
QMap<QCString,QValueList<int> >::Iterator i = _handles.begin();
01110 i != _handles.end();
01111 ++i) {
01112 i.data().remove(handle);
01113 }
01114 }
01115
01116
01117 KWallet::Backend *KWalletD::getWallet(
const QCString& appid,
int handle) {
01118
if (handle == 0) {
01119
return 0L;
01120 }
01121
01122 KWallet::Backend *w = _wallets.find(handle);
01123
01124
if (w) {
01125
if (_handles.contains(appid)) {
01126
if (_handles[appid].contains(handle)) {
01127
01128 _failed = 0;
01129
if (_closeIdle && _timeouts) {
01130 _timeouts->resetTimer(handle, _idleTime);
01131 }
01132
return w;
01133 }
01134 }
01135 }
01136
01137
if (++_failed > 5) {
01138 _failed = 0;
01139 QTimer::singleShot(0,
this, SLOT(notifyFailures()));
01140 }
01141
01142
return 0L;
01143 }
01144
01145
01146
void KWalletD::notifyFailures() {
01147
if (!_showingFailureNotify) {
01148 _showingFailureNotify =
true;
01149
KMessageBox::information(0, i18n(
"There have been repeated failed attempts to gain access to a wallet. An application may be misbehaving."), i18n(
"KDE Wallet Service"));
01150 _showingFailureNotify =
false;
01151 }
01152 }
01153
01154
01155
void KWalletD::doCloseSignals(
int handle,
const QString& wallet) {
01156
QByteArray data;
01157
QDataStream ds(data, IO_WriteOnly);
01158 ds << handle;
01159 emitDCOPSignal(
"walletClosed(int)", data);
01160
01161
QByteArray data2;
01162
QDataStream ds2(data2, IO_WriteOnly);
01163 ds2 << wallet;
01164 emitDCOPSignal(
"walletClosed(QString)", data2);
01165
01166
if (_wallets.isEmpty()) {
01167 emitDCOPSignal(
"allWalletsClosed()",
QByteArray());
01168 }
01169 }
01170
01171
01172
int KWalletD::renameEntry(
int handle,
const QString& folder,
const QString& oldName,
const QString& newName) {
01173 KWallet::Backend *b;
01174
01175
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
01176 b->setFolder(folder);
01177
int rc = b->renameEntry(oldName, newName);
01178 emitFolderUpdated(b->walletName(), folder);
01179
return rc;
01180 }
01181
01182
return -1;
01183 }
01184
01185
01186
QStringList KWalletD::users(
const QString& wallet)
const {
01187
QStringList rc;
01188
01189
for (
QIntDictIterator<KWallet::Backend> it(_wallets);
01190 it.current();
01191 ++it) {
01192
if (it.current()->walletName() == wallet) {
01193
for (
QMap<QCString,QValueList<int> >::ConstIterator hit = _handles.begin(); hit != _handles.end(); ++hit) {
01194
if (hit.data().contains(it.currentKey())) {
01195 rc += hit.key();
01196 }
01197 }
01198
break;
01199 }
01200 }
01201
01202
return rc;
01203 }
01204
01205
01206
bool KWalletD::disconnectApplication(
const QString& wallet,
const QCString& application) {
01207
for (
QIntDictIterator<KWallet::Backend> it(_wallets);
01208 it.current();
01209 ++it) {
01210
if (it.current()->walletName() == wallet) {
01211
if (_handles[application].contains(it.currentKey())) {
01212 _handles[application].remove(it.currentKey());
01213
01214
if (_handles[application].isEmpty()) {
01215 _handles.remove(application);
01216 }
01217
01218
if (it.current()->deref() == 0) {
01219
close(it.current()->walletName(),
true);
01220 }
01221
01222
QByteArray data;
01223
QDataStream ds(data, IO_WriteOnly);
01224 ds << wallet;
01225 ds << application;
01226 emitDCOPSignal(
"applicationDisconnected(QString,QCString)", data);
01227
01228
return true;
01229 }
01230 }
01231 }
01232
01233
return false;
01234 }
01235
01236
01237
void KWalletD::emitFolderUpdated(
const QString& wallet,
const QString& folder) {
01238
QByteArray data;
01239
QDataStream ds(data, IO_WriteOnly);
01240 ds << wallet;
01241 ds << folder;
01242 emitDCOPSignal(
"folderUpdated(QString,QString)", data);
01243 }
01244
01245
01246
void KWalletD::emitWalletListDirty() {
01247 emitDCOPSignal(
"walletListDirty()",
QByteArray());
01248 }
01249
01250
01251
void KWalletD::reconfigure() {
01252
KConfig cfg(
"kwalletrc");
01253 cfg.
setGroup(
"Wallet");
01254 _firstUse = cfg.
readBoolEntry(
"First Use",
true);
01255 _enabled = cfg.
readBoolEntry(
"Enabled",
true);
01256 _launchManager = cfg.
readBoolEntry(
"Launch Manager",
true);
01257 _leaveOpen = cfg.
readBoolEntry(
"Leave Open",
false);
01258
bool idleSave = _closeIdle;
01259 _closeIdle = cfg.
readBoolEntry(
"Close When Idle",
false);
01260 _openPrompt = cfg.
readBoolEntry(
"Prompt on Open",
true);
01261
int timeSave = _idleTime;
01262
01263 _idleTime = cfg.
readNumEntry(
"Idle Timeout", 10) * 60 * 1000;
01264
01265
if (cfg.
readBoolEntry(
"Close on Screensaver",
false)) {
01266 connectDCOPSignal(
"kdesktop",
"KScreensaverIface",
"KDE_start_screensaver()",
"closeAllWallets()",
false);
01267 }
else {
01268 disconnectDCOPSignal(
"kdesktop",
"KScreensaverIface",
"KDE_start_screensaver()",
"closeAllWallets()");
01269 }
01270
01271
01272
if (_closeIdle) {
01273
if (_idleTime != timeSave) {
01274
QIntDictIterator<KWallet::Backend> it(_wallets);
01275
for (; it.current(); ++it) {
01276 _timeouts->resetTimer(it.currentKey(), _idleTime);
01277 }
01278 }
01279
01280
if (!idleSave) {
01281
QIntDictIterator<KWallet::Backend> it(_wallets);
01282
for (; it.current(); ++it) {
01283 _timeouts->addTimer(it.currentKey(), _idleTime);
01284 }
01285 }
01286 }
else {
01287 _timeouts->clear();
01288 }
01289
01290
01291 _implicitAllowMap.clear();
01292 cfg.
setGroup(
"Auto Allow");
01293
QStringList entries = cfg.
entryMap(
"Auto Allow").keys();
01294
for (QStringList::Iterator i = entries.begin(); i != entries.end(); ++i) {
01295 _implicitAllowMap[*i] = cfg.
readListEntry(*i);
01296 }
01297
01298
01299 _implicitDenyMap.clear();
01300 cfg.
setGroup(
"Auto Deny");
01301 entries = cfg.
entryMap(
"Auto Deny").keys();
01302
for (QStringList::Iterator i = entries.begin(); i != entries.end(); ++i) {
01303 _implicitDenyMap[*i] = cfg.
readListEntry(*i);
01304 }
01305
01306
01307
if (!_enabled) {
01308
while (!_wallets.isEmpty()) {
01309
QIntDictIterator<KWallet::Backend> it(_wallets);
01310
if (!it.current()) {
01311
break;
01312 }
01313 closeWallet(it.current(), it.currentKey(),
true);
01314 }
01315 }
01316 }
01317
01318
01319
bool KWalletD::isEnabled()
const {
01320
return _enabled;
01321 }
01322
01323
01324
bool KWalletD::folderDoesNotExist(
const QString& wallet,
const QString& folder) {
01325
if (!wallets().contains(wallet)) {
01326
return true;
01327 }
01328
01329
for (
QIntDictIterator<KWallet::Backend> it(_wallets); it.current(); ++it) {
01330
if (it.current()->walletName() == wallet) {
01331
return it.current()->folderDoesNotExist(folder);
01332 }
01333 }
01334
01335 KWallet::Backend *b =
new KWallet::Backend(wallet);
01336 b->open(
QByteArray());
01337
bool rc = b->folderDoesNotExist(folder);
01338
delete b;
01339
return rc;
01340 }
01341
01342
01343
bool KWalletD::keyDoesNotExist(
const QString& wallet,
const QString& folder,
const QString& key) {
01344
if (!wallets().contains(wallet)) {
01345
return true;
01346 }
01347
01348
for (
QIntDictIterator<KWallet::Backend> it(_wallets); it.current(); ++it) {
01349
if (it.current()->walletName() == wallet) {
01350
return it.current()->entryDoesNotExist(folder, key);
01351 }
01352 }
01353
01354 KWallet::Backend *b =
new KWallet::Backend(wallet);
01355 b->open(
QByteArray());
01356
bool rc = b->entryDoesNotExist(folder, key);
01357
delete b;
01358
return rc;
01359 }
01360
01361
01362
bool KWalletD::implicitAllow(
const QString& wallet,
const QCString& app) {
01363
return _implicitAllowMap[wallet].contains(QString::fromLocal8Bit(app));
01364 }
01365
01366
01367
bool KWalletD::implicitDeny(
const QString& wallet,
const QCString& app) {
01368
return _implicitDenyMap[wallet].contains(QString::fromLocal8Bit(app));
01369 }
01370
01371
01372
QCString KWalletD::friendlyDCOPPeerName() {
01373
DCOPClient *dc = callingDcopClient();
01374
if (!dc) {
01375
return "";
01376 }
01377
return dc->
senderId().replace(
QRegExp(
"-[0-9]+$"),
"");
01378 }
01379
01380
01381
void KWalletD::timedOut(
int id) {
01382 KWallet::Backend *w = _wallets.find(
id);
01383
if (w) {
01384 closeWallet(w,
id,
true);
01385 }
01386 }
01387
01388
01389
void KWalletD::closeAllWallets() {
01390
QIntDict<KWallet::Backend> tw = _wallets;
01391
01392
for (
QIntDictIterator<KWallet::Backend> it(tw); it.current(); ++it) {
01393 closeWallet(it.current(), it.currentKey(),
true);
01394 }
01395
01396 tw.clear();
01397
01398
01399 _wallets.clear();
01400
01401
for (
QMap<QString,QCString>::Iterator it = _passwords.begin();
01402 it != _passwords.end();
01403 ++it) {
01404 it.data().fill(0);
01405 }
01406 _passwords.clear();
01407 }
01408
01409
01410
QString KWalletD::networkWallet() {
01411
return KWallet::Wallet::NetworkWallet();
01412 }
01413
01414
01415
QString KWalletD::localWallet() {
01416
return KWallet::Wallet::LocalWallet();
01417 }
01418
01419
01420
#include "kwalletd.moc"