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