2
* Copyright (C) 2003-2007 Justin Karneges <justin@affinix.com>
3
* Copyright (C) 2004,2005 Brad Hards <bradh@frogmouth.net>
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21
#include "qca_keystore.h"
23
#include <QCoreApplication>
24
#include <QAbstractEventDispatcher>
28
#include <QWaitCondition>
30
#include <stdlib.h> // abort
31
#include <stdio.h> // fprintf
33
#include "qcaprovider.h"
35
Q_DECLARE_METATYPE(QCA::KeyStoreEntry)
36
Q_DECLARE_METATYPE(QList<QCA::KeyStoreEntry>)
37
Q_DECLARE_METATYPE(QList<QCA::KeyStoreEntry::Type>)
38
Q_DECLARE_METATYPE(QCA::KeyBundle)
39
Q_DECLARE_METATYPE(QCA::Certificate)
40
Q_DECLARE_METATYPE(QCA::CRL)
41
Q_DECLARE_METATYPE(QCA::PGPKey)
45
Provider::Context *getContext(const QString &type, Provider *p);
50
KeyStoreListContext is queried for a list of store context ids. A signal
51
is used to indicate when the list may have changed, so polling for changes
52
is not necessary. Context ids change for every new presence of a store.
53
Even if a user removes and inserts the same smart card device, which has
54
the same storeId, the context id will ALWAYS be different. If a previously
55
known context id is missing from a later queried list, then it means the
56
associated store is unavailable. It is recommended that the provider just
57
use a counter for the contextId, incrementing the value anytime a new
60
KeyStoreTracker manages all of the keystore stuff, and exists in its own
61
thread (called the tracker thread). All of the KeyStoreListContext
62
objects exist in the tracker thread.
67
- ksm.start shouldn't block
68
- keystore in available list, but gone by the time it is requested
69
- keystore is unavailable during a call to a keystoreentry method
70
- keystore/keystoreentry methods called simultaneously from different threads
71
- and of course, objects from keystores should work, despite being created
72
in the keystore thread
75
//----------------------------------------------------------------------------
77
//----------------------------------------------------------------------------
78
static int tracker_id_at = 0;
80
class KeyStoreTracker : public QObject
84
static KeyStoreTracker *self;
89
// combine keystore owner and contextid into a single id
92
// number of times the keystore has been updated
96
KeyStoreListContext *owner;
105
Item() : trackerId(-1), updateCount(0), owner(0), storeContextId(-1)
111
QSet<KeyStoreListContext*> sources;
112
QSet<KeyStoreListContext*> busySources;
124
qRegisterMetaType<QCA::KeyStoreEntry>("QCA::KeyStoreEntry");
125
qRegisterMetaType< QList<QCA::KeyStoreEntry> >("QList<QCA::KeyStoreEntry>");
126
qRegisterMetaType< QList<QCA::KeyStoreEntry::Type> >("QList<QCA::KeyStoreEntry::Type>");
128
connect(this, SIGNAL(updated_p()), SLOT(updated_locked()), Qt::QueuedConnection);
131
busy = true; // we start out busy
140
static KeyStoreTracker *instance()
148
QMutexLocker locker(&m);
153
QList<Item> getItems()
155
QMutexLocker locker(&m);
162
QMutexLocker locker(&m);
169
QMutexLocker locker(&m);
174
void addTarget(QObject *ksm)
176
QMutexLocker locker(&updateMutex);
177
ksm->connect(this, SIGNAL(updated()), SLOT(tracker_updated()), Qt::DirectConnection);
181
void removeTarget(QObject *ksm)
183
QMutexLocker locker(&updateMutex);
190
QAbstractEventDispatcher::instance()->processEvents(QEventLoop::AllEvents);
195
// grab providers (and default)
196
ProviderList list = providers();
197
list.append(defaultProvider());
199
for(int n = 0; n < list.count(); ++n)
201
Provider *p = list[n];
202
if(p->features().contains("keystorelist") && !haveProviderSource(p))
209
void start(const QString &provider)
211
// grab providers (and default)
212
ProviderList list = providers();
213
list.append(defaultProvider());
216
for(int n = 0; n < list.count(); ++n)
218
if(list[n]->name() == provider)
225
if(p && p->features().contains("keystorelist") && !haveProviderSource(p))
235
QList<QCA::KeyStoreEntry> entryList(int trackerId)
237
QList<KeyStoreEntry> out;
238
int at = findItem(trackerId);
242
QList<KeyStoreEntryContext*> list = i.owner->entryList(i.storeContextId);
243
for(int n = 0; n < list.count(); ++n)
246
entry.change(list[n]);
252
QList<QCA::KeyStoreEntry::Type> entryTypes(int trackerId)
254
QList<KeyStoreEntry::Type> out;
255
int at = findItem(trackerId);
259
return i.owner->entryTypes(i.storeContextId);
263
void *entry(const QString &storeId, const QString &entryId)
265
KeyStoreListContext *c = 0;
268
foreach(Item i, items)
270
if(i.storeId == storeId)
273
contextId = i.storeContextId;
281
return c->entry(contextId, entryId);
285
void *entryPassive(const QString &serialized)
287
foreach(KeyStoreListContext *ksl, sources)
290
KeyStoreEntryContext *e = ksl->entryPassive(serialized);
297
QString writeEntry(int trackerId, const QVariant &v)
299
int at = findItem(trackerId);
303
if(qVariantCanConvert<KeyBundle>(v))
304
return i.owner->writeEntry(i.storeContextId, qVariantValue<KeyBundle>(v));
305
else if(qVariantCanConvert<Certificate>(v))
306
return i.owner->writeEntry(i.storeContextId, qVariantValue<Certificate>(v));
307
else if(qVariantCanConvert<CRL>(v))
308
return i.owner->writeEntry(i.storeContextId, qVariantValue<CRL>(v));
309
else if(qVariantCanConvert<PGPKey>(v))
310
return i.owner->writeEntry(i.storeContextId, qVariantValue<PGPKey>(v));
315
bool removeEntry(int trackerId, const QString &entryId)
317
int at = findItem(trackerId);
321
return i.owner->removeEntry(i.storeContextId, entryId);
325
// emit this when items or busy state changes
330
void updated_locked()
332
QMutexLocker locker(&updateMutex);
337
bool haveProviderSource(Provider *p) const
339
foreach(KeyStoreListContext *ksl, sources)
341
if(ksl->provider() == p)
347
int findItem(int trackerId)
349
for(int n = 0; n < items.count(); ++n)
351
if(items[n].trackerId == trackerId)
357
void startProvider(Provider *p)
359
KeyStoreListContext *c = static_cast<KeyStoreListContext *>(getContext("keystorelist", p));
365
connect(c, SIGNAL(busyStart()), SLOT(ksl_busyStart()));
366
connect(c, SIGNAL(busyEnd()), SLOT(ksl_busyEnd()));
367
connect(c, SIGNAL(updated()), SLOT(ksl_updated()));
368
connect(c, SIGNAL(diagnosticText(const QString &)), SLOT(ksl_diagnosticText(const QString &)));
369
connect(c, SIGNAL(storeUpdated(int)), SLOT(ksl_storeUpdated(int)));
371
c->setUpdatesEnabled(true);
373
QCA_logTextMessage(QString("keystore: startProvider %1").arg(p->name()), Logger::Information);
376
bool updateStores(KeyStoreListContext *c)
378
bool changed = false;
380
QMutexLocker locker(&m);
382
QList<int> keyStores = c->keyStores();
384
// remove any contexts that are gone
385
for(int n = 0; n < items.count(); ++n)
387
if(items[n].owner == c && !keyStores.contains(items[n].storeContextId))
389
QCA_logTextMessage(QString("keystore: updateStores remove %1").arg(items[n].storeContextId), Logger::Information);
392
--n; // adjust position
398
// handle add/updates
399
foreach(int id, keyStores)
401
// do we have it already?
403
for(int n = 0; n < items.count(); ++n)
405
if(items[n].owner == c && items[n].storeContextId == id)
417
QString name = c->name(id);
418
bool isReadOnly = c->isReadOnly(id);
419
if(i.name != name || i.isReadOnly != isReadOnly)
421
QCA_logTextMessage(QString("keystore: updateStores update %1").arg(id), Logger::Information);
423
i.isReadOnly = isReadOnly;
430
QCA_logTextMessage(QString("keystore: updateStores add %1").arg(id), Logger::Information);
433
i.trackerId = tracker_id_at++;
436
i.storeContextId = id;
437
i.storeId = c->storeId(id);
438
i.name = c->name(id);
439
i.type = c->type(id);
440
i.isReadOnly = c->isReadOnly(id);
453
KeyStoreListContext *c = (KeyStoreListContext *)sender();
455
QCA_logTextMessage(QString("keystore: ksl_busyStart %1").arg(c->provider()->name()), Logger::Information);
457
if(!busySources.contains(c))
461
QCA_logTextMessage(QString("keystore: emitting updated"), Logger::Information);
468
KeyStoreListContext *c = (KeyStoreListContext *)sender();
470
QCA_logTextMessage(QString("keystore: ksl_busyEnd %1").arg(c->provider()->name()), Logger::Information);
472
busySources.remove(c);
473
bool changed = updateStores(c);
474
bool any_busy = !busySources.isEmpty();
483
if(!any_busy || changed)
485
QCA_logTextMessage(QString("keystore: emitting updated"), Logger::Information);
492
KeyStoreListContext *c = (KeyStoreListContext *)sender();
494
QCA_logTextMessage(QString("keystore: ksl_updated %1").arg(c->provider()->name()), Logger::Information);
496
bool changed = updateStores(c);
499
QCA_logTextMessage(QString("keystore: emitting updated"), Logger::Information);
504
void ksl_diagnosticText(const QString &str)
506
QMutexLocker locker(&m);
510
void ksl_storeUpdated(int id)
512
KeyStoreListContext *c = (KeyStoreListContext *)sender();
514
QCA_logTextMessage(QString("keystore: ksl_storeUpdated %1 %2").arg(c->provider()->name(), QString::number(id)), Logger::Information);
516
QMutexLocker locker(&m);
517
for(int n = 0; n < items.count(); ++n)
520
if(i.owner == c && i.storeContextId == id)
524
QCA_logTextMessage(QString("keystore: %1 updateCount = %2").arg(i.name, QString::number(i.updateCount)), Logger::Information);
526
QCA_logTextMessage(QString("keystore: emitting updated"), Logger::Information);
534
KeyStoreTracker *KeyStoreTracker::self = 0;
536
//----------------------------------------------------------------------------
538
//----------------------------------------------------------------------------
539
class KeyStoreThread : public SyncThread
543
KeyStoreTracker *tracker;
546
KeyStoreThread(QObject *parent = 0) : SyncThread(parent)
557
tracker = new KeyStoreTracker;
566
//----------------------------------------------------------------------------
568
//----------------------------------------------------------------------------
569
class KeyStoreManagerGlobal;
571
Q_GLOBAL_STATIC(QMutex, ksm_mutex)
572
static KeyStoreManagerGlobal *g_ksm = 0;
574
class KeyStoreManagerGlobal
577
KeyStoreThread *thread;
579
KeyStoreManagerGlobal()
581
thread = new KeyStoreThread;
582
thread->moveToThread(QCoreApplication::instance()->thread());
586
~KeyStoreManagerGlobal()
592
// this function is thread-safe
593
static QVariant trackercall(const char *method, const QVariantList &args = QVariantList())
598
g_ksm->thread->call_mutex.lock();
599
ret = g_ksm->thread->call(KeyStoreTracker::instance(), method, args, &ok);
600
g_ksm->thread->call_mutex.unlock();
605
fprintf(stderr, "QCA: KeyStoreTracker call [%s] failed.\n", method);
612
//----------------------------------------------------------------------------
614
//----------------------------------------------------------------------------
615
class KeyStoreEntry::Private
626
KeyStoreEntry::KeyStoreEntry()
631
KeyStoreEntry::KeyStoreEntry(const QString &serialized)
634
*this = fromString(serialized);
637
KeyStoreEntry::KeyStoreEntry(const KeyStoreEntry &from)
638
:Algorithm(from), d(new Private(*from.d))
642
KeyStoreEntry::~KeyStoreEntry()
647
KeyStoreEntry & KeyStoreEntry::operator=(const KeyStoreEntry &from)
649
Algorithm::operator=(from);
654
bool KeyStoreEntry::isNull() const
656
return (!context() ? true : false);
659
bool KeyStoreEntry::isAvailable() const
661
return static_cast<const KeyStoreEntryContext *>(context())->isAvailable();
664
bool KeyStoreEntry::isAccessible() const
666
return d->accessible;
669
KeyStoreEntry::Type KeyStoreEntry::type() const
671
return static_cast<const KeyStoreEntryContext *>(context())->type();
674
QString KeyStoreEntry::name() const
676
return static_cast<const KeyStoreEntryContext *>(context())->name();
679
QString KeyStoreEntry::id() const
681
return static_cast<const KeyStoreEntryContext *>(context())->id();
684
QString KeyStoreEntry::storeName() const
686
return static_cast<const KeyStoreEntryContext *>(context())->storeName();
689
QString KeyStoreEntry::storeId() const
691
return static_cast<const KeyStoreEntryContext *>(context())->storeId();
694
QString KeyStoreEntry::toString() const
696
return static_cast<const KeyStoreEntryContext *>(context())->serialize();
699
KeyStoreEntry KeyStoreEntry::fromString(const QString &serialized)
702
KeyStoreEntryContext *c = (KeyStoreEntryContext *)KeyStoreTracker::instance()->entryPassive(serialized);
708
KeyBundle KeyStoreEntry::keyBundle() const
710
return static_cast<const KeyStoreEntryContext *>(context())->keyBundle();
713
Certificate KeyStoreEntry::certificate() const
715
return static_cast<const KeyStoreEntryContext *>(context())->certificate();
718
CRL KeyStoreEntry::crl() const
720
return static_cast<const KeyStoreEntryContext *>(context())->crl();
723
PGPKey KeyStoreEntry::pgpSecretKey() const
725
return static_cast<const KeyStoreEntryContext *>(context())->pgpSecretKey();
728
PGPKey KeyStoreEntry::pgpPublicKey() const
730
return static_cast<const KeyStoreEntryContext *>(context())->pgpPublicKey();
733
bool KeyStoreEntry::ensureAvailable()
735
QString storeId = this->storeId();
736
QString entryId = id();
737
KeyStoreEntryContext *c = (KeyStoreEntryContext *)qVariantValue<void*>(trackercall("entry", QVariantList() << storeId << entryId));
740
return isAvailable();
743
bool KeyStoreEntry::ensureAccess()
745
if(!ensureAvailable())
747
d->accessible = false;
750
bool ok = static_cast<KeyStoreEntryContext *>(context())->ensureAccess();
752
return d->accessible;
755
//----------------------------------------------------------------------------
756
// KeyStoreEntryWatcher
757
//----------------------------------------------------------------------------
758
class KeyStoreEntryWatcher::Private : public QObject
762
KeyStoreEntryWatcher *q;
765
QString storeId, entryId;
769
Private(KeyStoreEntryWatcher *_q) : QObject(_q), q(_q), ksm(this)
773
connect(&ksm, SIGNAL(keyStoreAvailable(const QString &)), SLOT(ksm_available(const QString &)));
783
QStringList list = ksm.keyStores();
784
foreach(const QString &storeId, list)
785
ksm_available(storeId);
789
void ksm_available(const QString &_storeId)
791
// we only care about one store
792
if(_storeId == storeId)
794
ks = new KeyStore(storeId, &ksm);
795
connect(ks, SIGNAL(updated()), SLOT(ks_updated()));
796
ks->startAsynchronousMode();
803
QList<KeyStoreEntry> list = ks->entryList();
804
foreach(const KeyStoreEntry &e, list)
806
if(e.id() == entryId && e.isAvailable())
820
else if(!found && avail)
823
emit q->unavailable();
827
void ks_unavailable()
835
emit q->unavailable();
840
KeyStoreEntryWatcher::KeyStoreEntryWatcher(const KeyStoreEntry &e, QObject *parent)
843
d = new Private(this);
847
d->storeId = e.storeId();
853
KeyStoreEntryWatcher::~KeyStoreEntryWatcher()
858
KeyStoreEntry KeyStoreEntryWatcher::entry() const
863
//----------------------------------------------------------------------------
865
//----------------------------------------------------------------------------
867
class KeyStoreWriteEntry
870
enum Type { TypeKeyBundle, TypeCertificate, TypeCRL, TypePGPKey };
882
KeyStoreWriteEntry(const KeyBundle &_keyBundle)
883
:type(TypeKeyBundle), keyBundle(_keyBundle)
887
KeyStoreWriteEntry(const Certificate &_cert)
888
:type(TypeCertificate), cert(_cert)
892
KeyStoreWriteEntry(const CRL &_crl)
893
:type(TypeCRL), crl(_crl)
897
KeyStoreWriteEntry(const PGPKey &_pgpKey)
898
:type(TypePGPKey), pgpKey(_pgpKey)
903
class KeyStoreOperation : public QThread
907
enum Type { EntryList, WriteEntry, RemoveEntry };
912
KeyStoreWriteEntry wentry; // in: WriteEntry
913
QList<KeyStoreEntry> entryList; // out: EntryList
914
QString entryId; // in: RemoveEntry, out: WriteEntry
915
bool success; // out: RemoveEntry
917
KeyStoreOperation(QObject *parent = 0)
930
if(type == EntryList)
931
entryList = qVariantValue< QList<KeyStoreEntry> >(trackercall("entryList", QVariantList() << trackerId));
932
else if(type == WriteEntry)
935
if(wentry.type == KeyStoreWriteEntry::TypeKeyBundle)
936
qVariantSetValue<KeyBundle>(arg, wentry.keyBundle);
937
else if(wentry.type == KeyStoreWriteEntry::TypeCertificate)
938
qVariantSetValue<Certificate>(arg, wentry.cert);
939
else if(wentry.type == KeyStoreWriteEntry::TypeCRL)
940
qVariantSetValue<CRL>(arg, wentry.crl);
941
else if(wentry.type == KeyStoreWriteEntry::TypePGPKey)
942
qVariantSetValue<PGPKey>(arg, wentry.pgpKey);
943
entryId = trackercall("writeEntry", QVariantList() << trackerId << arg).toString();
947
success = trackercall("removeEntry", QVariantList() << trackerId << entryId).toBool();
952
class KeyStorePrivate : public QObject
957
KeyStoreManager *ksm;
959
KeyStoreTracker::Item item;
962
QList<KeyStoreEntry> latestEntryList;
963
QList<KeyStoreOperation*> ops;
965
KeyStorePrivate(KeyStore *_q) : QObject(_q), q(_q), async(false)
974
// implemented below, after KeyStorePrivate is declared
977
KeyStoreTracker::Item *getItem(const QString &storeId);
978
KeyStoreTracker::Item *getItem(int trackerId);
986
bool have_entryList_op() const
988
foreach(KeyStoreOperation *op, ops)
990
if(op->type == KeyStoreOperation::EntryList)
996
void handle_updated()
1000
if(!have_entryList_op())
1009
void async_entryList()
1011
KeyStoreOperation *op = new KeyStoreOperation(this);
1012
// use queued for signal-safety
1013
connect(op, SIGNAL(finished()), SLOT(op_finished()), Qt::QueuedConnection);
1014
op->type = KeyStoreOperation::EntryList;
1015
op->trackerId = trackerId;
1020
void async_writeEntry(const KeyStoreWriteEntry &wentry)
1022
KeyStoreOperation *op = new KeyStoreOperation(this);
1023
// use queued for signal-safety
1024
connect(op, SIGNAL(finished()), SLOT(op_finished()), Qt::QueuedConnection);
1025
op->type = KeyStoreOperation::WriteEntry;
1026
op->trackerId = trackerId;
1027
op->wentry = wentry;
1032
void async_removeEntry(const QString &entryId)
1034
KeyStoreOperation *op = new KeyStoreOperation(this);
1035
// use queued for signal-safety
1036
connect(op, SIGNAL(finished()), SLOT(op_finished()), Qt::QueuedConnection);
1037
op->type = KeyStoreOperation::RemoveEntry;
1038
op->trackerId = trackerId;
1039
op->entryId = entryId;
1047
KeyStoreOperation *op = (KeyStoreOperation *)sender();
1049
if(op->type == KeyStoreOperation::EntryList)
1051
latestEntryList = op->entryList;
1057
need_update = false;
1063
else if(op->type == KeyStoreOperation::WriteEntry)
1065
QString entryId = op->entryId;
1069
emit q->entryWritten(entryId);
1073
bool success = op->success;
1077
emit q->entryRemoved(success);
1082
KeyStore::KeyStore(const QString &id, KeyStoreManager *keyStoreManager)
1083
:QObject(keyStoreManager)
1085
d = new KeyStorePrivate(this);
1086
d->ksm = keyStoreManager;
1088
KeyStoreTracker::Item *i = d->getItem(id);
1091
d->trackerId = i->trackerId;
1099
KeyStore::~KeyStore()
1101
if(d->trackerId != -1)
1106
bool KeyStore::isValid() const
1108
return (d->getItem(d->trackerId) ? true : false);
1111
KeyStore::Type KeyStore::type() const
1113
return d->item.type;
1116
QString KeyStore::name() const
1118
return d->item.name;
1121
QString KeyStore::id() const
1123
return d->item.storeId;
1126
bool KeyStore::isReadOnly() const
1128
return d->item.isReadOnly;
1131
void KeyStore::startAsynchronousMode()
1138
// initial entrylist
1139
d->need_update = false;
1140
d->async_entryList();
1143
QList<KeyStoreEntry> KeyStore::entryList() const
1146
return d->latestEntryList;
1148
if(d->trackerId == -1)
1149
return QList<KeyStoreEntry>();
1150
return qVariantValue< QList<KeyStoreEntry> >(trackercall("entryList", QVariantList() << d->trackerId));
1153
bool KeyStore::holdsTrustedCertificates() const
1155
QList<KeyStoreEntry::Type> list;
1156
if(d->trackerId == -1)
1158
list = qVariantValue< QList<KeyStoreEntry::Type> >(trackercall("entryTypes", QVariantList() << d->trackerId));
1159
if(list.contains(KeyStoreEntry::TypeCertificate) || list.contains(KeyStoreEntry::TypeCRL))
1164
bool KeyStore::holdsIdentities() const
1166
QList<KeyStoreEntry::Type> list;
1167
if(d->trackerId == -1)
1169
list = qVariantValue< QList<KeyStoreEntry::Type> >(trackercall("entryTypes", QVariantList() << d->trackerId));
1170
if(list.contains(KeyStoreEntry::TypeKeyBundle) || list.contains(KeyStoreEntry::TypePGPSecretKey))
1175
bool KeyStore::holdsPGPPublicKeys() const
1177
QList<KeyStoreEntry::Type> list;
1178
if(d->trackerId == -1)
1180
list = qVariantValue< QList<KeyStoreEntry::Type> >(trackercall("entryTypes", QVariantList() << d->trackerId));
1181
if(list.contains(KeyStoreEntry::TypePGPPublicKey))
1186
QString KeyStore::writeEntry(const KeyBundle &kb)
1190
d->async_writeEntry(KeyStoreWriteEntry(kb));
1196
qVariantSetValue<KeyBundle>(arg, kb);
1197
return trackercall("writeEntry", QVariantList() << d->trackerId << arg).toString();
1201
QString KeyStore::writeEntry(const Certificate &cert)
1205
d->async_writeEntry(KeyStoreWriteEntry(cert));
1211
qVariantSetValue<Certificate>(arg, cert);
1212
return trackercall("writeEntry", QVariantList() << d->trackerId << arg).toString();
1216
QString KeyStore::writeEntry(const CRL &crl)
1220
d->async_writeEntry(KeyStoreWriteEntry(crl));
1226
qVariantSetValue<CRL>(arg, crl);
1227
return trackercall("writeEntry", QVariantList() << d->trackerId << arg).toString();
1231
QString KeyStore::writeEntry(const PGPKey &key)
1235
d->async_writeEntry(KeyStoreWriteEntry(key));
1241
qVariantSetValue<PGPKey>(arg, key);
1242
return trackercall("writeEntry", QVariantList() << d->trackerId << arg).toString();
1246
bool KeyStore::removeEntry(const QString &id)
1250
d->async_removeEntry(id);
1255
return trackercall("removeEntry", QVariantList() << d->trackerId << id).toBool();
1259
//----------------------------------------------------------------------------
1261
//----------------------------------------------------------------------------
1262
static void ensure_init()
1264
QMutexLocker locker(ksm_mutex());
1266
g_ksm = new KeyStoreManagerGlobal;
1270
void KeyStoreManager::start()
1273
QMetaObject::invokeMethod(KeyStoreTracker::instance(), "start", Qt::QueuedConnection);
1274
trackercall("spinEventLoop");
1277
void KeyStoreManager::start(const QString &provider)
1280
QMetaObject::invokeMethod(KeyStoreTracker::instance(), "start", Qt::QueuedConnection, Q_ARG(QString, provider));
1281
trackercall("spinEventLoop");
1284
QString KeyStoreManager::diagnosticText()
1288
// spin one event cycle in the tracker, to receive any pending text.
1289
// note that since trackercall also goes through the eventloop,
1290
// this may end up doing two rounds. probably no big deal.
1291
trackercall("spinEventLoop");
1293
return KeyStoreTracker::instance()->getDText();
1296
void KeyStoreManager::clearDiagnosticText()
1299
KeyStoreTracker::instance()->clearDText();
1302
void KeyStoreManager::scan()
1305
QMetaObject::invokeMethod(KeyStoreTracker::instance(), "scan", Qt::QueuedConnection);
1308
void KeyStoreManager::shutdown()
1310
QMutexLocker locker(ksm_mutex());
1316
class KeyStoreManagerPrivate : public QObject
1325
QList<KeyStoreTracker::Item> items;
1326
bool pending, waiting;
1328
QMultiHash<int,KeyStore*> keyStoreForTrackerId;
1329
QHash<KeyStore*,int> trackerIdForKeyStore;
1331
KeyStoreManagerPrivate(KeyStoreManager *_q) : QObject(_q), q(_q)
1337
~KeyStoreManagerPrivate()
1339
// invalidate registered keystores
1340
QList<KeyStore*> list;
1341
QHashIterator<KeyStore*,int> it(trackerIdForKeyStore);
1347
foreach(KeyStore *ks, list)
1348
ks->d->invalidate();
1352
void reg(KeyStore *ks, int trackerId)
1354
keyStoreForTrackerId.insert(trackerId, ks);
1355
trackerIdForKeyStore.insert(ks, trackerId);
1358
void unreg(KeyStore *ks)
1360
int trackerId = trackerIdForKeyStore.take(ks);
1362
// this is the only way I know to remove one item from a multihash
1363
QList<KeyStore*> vals = keyStoreForTrackerId.values(trackerId);
1364
keyStoreForTrackerId.remove(trackerId);
1366
foreach(KeyStore *i, vals)
1367
keyStoreForTrackerId.insert(trackerId, i);
1370
KeyStoreTracker::Item *getItem(const QString &storeId)
1372
for(int n = 0; n < items.count(); ++n)
1374
KeyStoreTracker::Item *i = &items[n];
1375
if(i->storeId == storeId)
1381
KeyStoreTracker::Item *getItem(int trackerId)
1383
for(int n = 0; n < items.count(); ++n)
1385
KeyStoreTracker::Item *i = &items[n];
1386
if(i->trackerId == trackerId)
1394
// ksm doesn't have reset or state changes so we can
1395
// use QPointer here for full SS.
1396
QPointer<QObject> self(this);
1398
bool newbusy = KeyStoreTracker::instance()->isBusy();
1399
QList<KeyStoreTracker::Item> newitems = KeyStoreTracker::instance()->getItems();
1401
if(!busy && newbusy)
1403
emit q->busyStarted();
1407
if(busy && !newbusy)
1409
emit q->busyFinished();
1419
for(int n = 0; n < items.count(); ++n)
1421
KeyStoreTracker::Item &i = items[n];
1423
for(int k = 0; k < newitems.count(); ++k)
1425
if(i.trackerId == newitems[k].trackerId)
1432
gone += i.trackerId;
1436
for(int n = 0; n < items.count(); ++n)
1438
KeyStoreTracker::Item &i = items[n];
1439
for(int k = 0; k < newitems.count(); ++k)
1441
if(i.trackerId == newitems[k].trackerId)
1443
if(i.updateCount < newitems[k].updateCount)
1444
changed += i.trackerId;
1451
for(int n = 0; n < newitems.count(); ++n)
1453
KeyStoreTracker::Item &i = newitems[n];
1455
for(int k = 0; k < items.count(); ++k)
1457
if(i.trackerId == items[k].trackerId)
1471
foreach(int trackerId, gone)
1473
KeyStore *ks = keyStoreForTrackerId.value(trackerId);
1476
ks->d->invalidate();
1477
emit ks->unavailable();
1483
foreach(int trackerId, changed)
1485
KeyStore *ks = keyStoreForTrackerId.value(trackerId);
1488
ks->d->handle_updated();
1494
foreach(QString storeId, here)
1496
emit q->keyStoreAvailable(storeId);
1503
void tracker_updated()
1505
QCA_logTextMessage(QString().sprintf("keystore: %p: tracker_updated start", q), Logger::Information);
1507
QMutexLocker locker(&m);
1510
QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection);
1513
if(waiting && !KeyStoreTracker::instance()->isBusy())
1516
items = KeyStoreTracker::instance()->getItems();
1520
QCA_logTextMessage(QString().sprintf("keystore: %p: tracker_updated end", q), Logger::Information);
1533
// from KeyStorePrivate
1534
void KeyStorePrivate::reg()
1536
ksm->d->reg(q, trackerId);
1539
void KeyStorePrivate::unreg()
1544
KeyStoreTracker::Item *KeyStorePrivate::getItem(const QString &storeId)
1546
return ksm->d->getItem(storeId);
1549
KeyStoreTracker::Item *KeyStorePrivate::getItem(int trackerId)
1551
return ksm->d->getItem(trackerId);
1554
KeyStoreManager::KeyStoreManager(QObject *parent)
1558
d = new KeyStoreManagerPrivate(this);
1559
KeyStoreTracker::instance()->addTarget(d);
1563
KeyStoreManager::~KeyStoreManager()
1565
Q_ASSERT(KeyStoreTracker::instance());
1566
KeyStoreTracker::instance()->removeTarget(d);
1570
bool KeyStoreManager::isBusy() const
1575
void KeyStoreManager::waitForBusyFinished()
1578
d->busy = KeyStoreTracker::instance()->isBusy();
1588
QStringList KeyStoreManager::keyStores() const
1591
for(int n = 0; n < d->items.count(); ++n)
1592
out += d->items[n].storeId;
1596
void KeyStoreManager::sync()
1598
d->busy = KeyStoreTracker::instance()->isBusy();
1599
d->items = KeyStoreTracker::instance()->getItems();
1602
//----------------------------------------------------------------------------
1604
//----------------------------------------------------------------------------
1605
class KeyStoreInfo::Private : public QSharedData
1608
KeyStore::Type type;
1612
KeyStoreInfo::KeyStoreInfo()
1616
KeyStoreInfo::KeyStoreInfo(KeyStore::Type type, const QString &id, const QString &name)
1624
KeyStoreInfo::KeyStoreInfo(const KeyStoreInfo &from)
1629
KeyStoreInfo::~KeyStoreInfo()
1633
KeyStoreInfo & KeyStoreInfo::operator=(const KeyStoreInfo &from)
1639
bool KeyStoreInfo::isNull() const
1641
return (d ? false: true);
1644
KeyStore::Type KeyStoreInfo::type() const
1649
QString KeyStoreInfo::id() const
1654
QString KeyStoreInfo::name() const
1661
#include "qca_keystore.moc"