keystore api update for passive entries, initial refactor of keystore backend

svn path=/trunk/kdesupport/qca/; revision=646458
This commit is contained in:
Justin Karneges 2007-03-25 19:36:00 +00:00
parent 1e7fa767af
commit 66e98c2371
6 changed files with 1151 additions and 731 deletions

View File

@ -384,12 +384,6 @@ namespace QCA
*/
QCA_EXPORT void setGlobalRNG(const QString &provider);
/**
Return a reference to the KeyStoreManager, which is used to interface with
system storage, PGP keyrings, and smart cards.
*/
QCA_EXPORT KeyStoreManager *keyStoreManager();
/**
Return a reference to the %QCA Logger, which is used for diagnostics
and error recording.

View File

@ -38,8 +38,8 @@
namespace QCA
{
class KeyStoreTracker;
class KeyStoreThread;
class KeyStoreManagerPrivate;
class KeyStorePrivate;
/**
\class KeyStoreEntry qca_keystore.h QtCrypto
@ -68,12 +68,18 @@ namespace QCA
*/
KeyStoreEntry();
/**
Create a passive KeyStoreEntry based on known entry
*/
KeyStoreEntry(const QString &id);
/**
Standard copy constructor
\param from the source entry
*/
KeyStoreEntry(const KeyStoreEntry &from);
~KeyStoreEntry();
/**
@ -88,6 +94,9 @@ namespace QCA
*/
bool isNull() const;
bool isAvailable() const;
bool isAccessible() const;
/**
Determine the type of key stored in this object
*/
@ -99,10 +108,15 @@ namespace QCA
QString name() const;
/**
The ID associated with the key stored in this object
The ID associated with the key stored in this object.
The ID is unique across all stores, and may be very long.
*/
QString id() const;
QString storeName() const;
QString storeId() const;
/**
If a KeyBundle is stored in this object, return that
bundle.
@ -134,9 +148,47 @@ namespace QCA
*/
PGPKey pgpPublicKey() const;
/**
Returns true if the entry is available, otherwise false.
Available means that the retrieval functions (like
keyBundle(), certificate(), pgpPublicKey(), etc) will
return non-null objects. Entries retrieved from a
KeyStore are always available, and therefore it is not
necessary to call this function. Calling this function
on an already available entry may cause the entry to
be refreshed.
\note This function is blocking.
*/
bool ensureAvailable();
// like ensureAvailable, but also login to the token if needed
bool ensureAccess();
private:
class Private;
Private *d;
friend class KeyStoreTracker;
};
class QCA_EXPORT KeyStoreEntryWatcher : public QObject
{
Q_OBJECT
public:
KeyStoreEntryWatcher(const KeyStoreEntry &e, QObject *parent = 0);
~KeyStoreEntryWatcher();
KeyStoreEntry entry() const;
signals:
void available();
void unavailable();
private:
class Private;
friend class Private;
Private *d;
};
/**
@ -158,7 +210,6 @@ namespace QCA
becomes invalid (isValid() == false), and unavailable() is emitted.
even if the device later reappears, the KeyStore remains invalid.
a new KeyStore will have to be created to use the device again.
*/
class QCA_EXPORT KeyStore : public QObject, public Algorithm
{
@ -180,9 +231,9 @@ namespace QCA
Obtain a specific KeyStore
\param id the identification for the key store
\param parent the parent object for this keystore
\param keyStoreManager the parent manager for this keystore
*/
KeyStore(const QString &id, QObject *parent = 0);
KeyStore(const QString &id, KeyStoreManager *keyStoreManager);
~KeyStore();
@ -284,12 +335,10 @@ namespace QCA
void unavailable();
private:
class Private;
Private *d;
friend class KeyStorePrivate;
KeyStorePrivate *d;
friend class KeyStoreTracker;
friend class KeyStoreManager;
void invalidate();
friend class KeyStoreManagerPrivate;
};
/**
@ -307,15 +356,18 @@ namespace QCA
{
Q_OBJECT
public:
KeyStoreManager(QObject *parent = 0);
~KeyStoreManager();
/**
Initialize all key store providers
*/
void start();
static void start();
/**
Initialize a specific key store provider
*/
void start(const QString &provider);
static void start(const QString &provider);
/**
Indicates if the manager is busy looking for key stores
@ -332,25 +384,31 @@ namespace QCA
*/
QStringList keyStores() const;
/**
The number of key stores that are currently available
*/
int count() const;
/**
The diagnostic result of key store operations, such as
warnings and errors
*/
QString diagnosticText() const;
static QString diagnosticText();
/**
Clears the diagnostic result log
*/
void clearDiagnosticText();
static void clearDiagnosticText();
/**
If you are not using the eventloop, call this to update
the object state to the present
*/
void sync();
signals:
/**
emitted when the manager is done looking for key stores
emitted when the manager has started looking for key stores
*/
void busyStarted();
/**
emitted when the manager has finished looking for key stores
*/
void busyFinished();
@ -364,13 +422,15 @@ namespace QCA
KeyStoreManagerPrivate *d;
friend class Global;
friend class KeyStoreTracker;
friend class KeyStoreThread;
KeyStoreManager();
~KeyStoreManager();
friend class KeyStorePrivate;
void scan() const;
static void scan();
static void shutdown();
};
}
Q_DECLARE_METATYPE(QCA::KeyStoreEntry)
Q_DECLARE_METATYPE(QList<QCA::KeyStoreEntry>)
Q_DECLARE_METATYPE(QList<QCA::KeyStoreEntry::Type>)
#endif

View File

@ -56,25 +56,28 @@ public:
QMutex manager_mutex;
ProviderManager manager;
Random *rng;
KeyStoreManager *ksm;
Logger *logger;
Logger *logger;
QVariantMap properties;
QMap<QString,QVariantMap> config;
Global()
{
rng = 0;
ksm = new KeyStoreManager;
logger = new Logger;
logger = new Logger;
secmem = false;
}
~Global()
{
delete ksm;
delete logger;
KeyStoreManager::shutdown();
delete logger;
delete rng;
}
void ksm_scan()
{
KeyStoreManager::scan();
}
};
static Global *global = 0;
@ -274,9 +277,12 @@ Provider *defaultProvider()
void scanForPlugins()
{
QMutexLocker lock(&global->manager_mutex);
{
QMutexLocker lock(&global->manager_mutex);
global->manager.scan();
global->manager.scan();
}
global->ksm_scan();
}
void unloadAllPlugins()
@ -448,11 +454,6 @@ void setGlobalRNG(const QString &provider)
global->rng = new Random(provider);
}
KeyStoreManager *keyStoreManager()
{
return global->ksm;
}
Logger *logger()
{
return global->logger;
@ -466,13 +467,14 @@ void logText( const QString &message, Logger::Severity severity )
bool haveSystemStore()
{
// ensure the system store is loaded
global->ksm->start("default");
global->ksm->waitForBusyFinished();
KeyStoreManager::start("default");
KeyStoreManager ksm;
ksm.waitForBusyFinished();
QStringList list = global->ksm->keyStores();
QStringList list = ksm.keyStores();
for(int n = 0; n < list.count(); ++n)
{
KeyStore ks(list[n]);
KeyStore ks(list[n], &ksm);
if(ks.type() == KeyStore::System && ks.holdsTrustedCertificates())
return true;
}
@ -482,14 +484,15 @@ bool haveSystemStore()
CertificateCollection systemStore()
{
// ensure the system store is loaded
global->ksm->start("default");
global->ksm->waitForBusyFinished();
KeyStoreManager::start("default");
KeyStoreManager ksm;
ksm.waitForBusyFinished();
CertificateCollection col;
QStringList list = global->ksm->keyStores();
QStringList list = ksm.keyStores();
for(int n = 0; n < list.count(); ++n)
{
KeyStore ks(list[n]);
KeyStore ks(list[n], &ksm);
// system store
if(ks.type() == KeyStore::System && ks.holdsTrustedCertificates())

View File

@ -709,6 +709,65 @@ public:
//----------------------------------------------------------------------------
// DefaultKeyStoreEntry
//----------------------------------------------------------------------------
static QString escape_string(const QString &in)
{
QString out;
for(int n = 0; n < in.length(); ++n)
{
if(in[n] == '\\')
out += "\\\\";
else if(in[n] == ':')
out += "\\c";
else
out += in[n];
}
return out;
}
static QString unescape_string(const QString &in)
{
QString out;
for(int n = 0; n < in.length(); ++n)
{
if(in[n] == '\\')
{
if(n + 1 < in.length())
{
if(in[n + 1] == '\\')
out += '\\';
else if(in[n + 1] == 'c')
out += ':';
}
}
else
out += in[n];
}
return out;
}
static QString makeId(const QString &storeId, const QString &storeName, const QString &entryId, const QString &entryName)
{
QStringList out;
out += escape_string("qca_def");
out += escape_string(storeId);
out += escape_string(storeName);
out += escape_string(entryId);
out += escape_string(entryName);
return out.join(":");
}
static bool parseId(const QString &in, QString *storeId, QString *storeName, QString *entryId, QString *entryName)
{
QStringList list = in.split(':');
if(list.count() != 5)
return false;
*storeId = unescape_string(list[1]);
*storeName = unescape_string(list[2]);
*entryId = unescape_string(list[3]);
*entryName = unescape_string(list[4]);
return true;
}
class DefaultKeyStoreEntry : public KeyStoreEntryContext
{
public:
@ -717,6 +776,8 @@ public:
Certificate _cert;
CRL _crl;
QString item_name;
DefaultKeyStoreEntry(const Certificate &cert, const QString &storeId, const QString &storeName, Provider *p) : KeyStoreEntryContext(p)
{
_storeId = storeId;
@ -757,6 +818,11 @@ public:
}
virtual QString name() const
{
return item_name;
}
QString makeName() const
{
// use the common name, else orgname
if(item_type == KeyStoreEntry::TypeCertificate)
@ -872,17 +938,38 @@ public:
for(n = 0; n < certs.count(); ++n)
{
DefaultKeyStoreEntry *c = new DefaultKeyStoreEntry(certs[n], storeId(0), name(0), provider());
c->item_id = QString::number(n);
//c->item_id = QString::number(n);
QString ename = c->makeName();
QString eid = QString::number(qHash(certs[n].toDER().toByteArray()));
c->item_name = ename;
c->item_id = makeId(storeId(0), name(0), eid, ename);
out.append(c);
}
for(n = 0; n < crls.count(); ++n)
{
DefaultKeyStoreEntry *c = new DefaultKeyStoreEntry(crls[n], storeId(0), name(0), provider());
c->item_name = c->makeName();
c->item_id = QString::number(n); // FIXME
out.append(c);
}
return out;
}
// TODO
KeyStoreEntryContext *entryPassive(const QString &_storeId, const QString &entryId)
{
Q_UNUSED(_storeId);
QString storeId, storeName, eid, ename;
if(parseId(entryId, &storeId, &storeName, &eid, &ename))
{
DefaultKeyStoreEntry *c = new DefaultKeyStoreEntry(Certificate(), storeId, storeName, provider());
c->item_name = ename;
c->item_id = eid;
return c;
}
return 0;
}
};
//----------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -182,7 +182,8 @@ private slots:
if(e.source() == QCA::Event::KeyStore)
{
QString name = "keystore";
QCA::KeyStore ks(e.keyStoreId());
QCA::KeyStoreManager ksm;
QCA::KeyStore ks(e.keyStoreId(), &ksm);
if(ks.isValid())
name = ks.name();
@ -537,12 +538,12 @@ static bool open_mime_data_sig(const QString &in, QString *data, QString *sig)
}
// first = ids, second = names
static QPair<QStringList, QStringList> getKeyStoreStrings(const QStringList &list)
static QPair<QStringList, QStringList> getKeyStoreStrings(const QStringList &list, QCA::KeyStoreManager *ksm)
{
QPair<QStringList, QStringList> out;
for(int n = 0; n < list.count(); ++n)
{
QCA::KeyStore ks(list[n]);
QCA::KeyStore ks(list[n], ksm);
out.first.append(ks.id());
out.second.append(ks.name());
}
@ -593,9 +594,10 @@ static int findByString(const QPair<QStringList, QStringList> &in, const QString
static QString getKeyStore(const QString &name)
{
QCA::KeyStoreManager *ksm = QCA::keyStoreManager();
QStringList storeList = ksm->keyStores();
int n = findByString(getKeyStoreStrings(storeList), name);
//QCA::KeyStoreManager *ksm = QCA::keyStoreManager();
QCA::KeyStoreManager ksm;// = QCA::keyStoreManager();
QStringList storeList = ksm.keyStores();
int n = findByString(getKeyStoreStrings(storeList, &ksm), name);
if(n != -1)
return storeList[n];
return QString();
@ -622,7 +624,8 @@ static QPair<QCA::PGPKey, QCA::PGPKey> getPGPSecretKey(const QString &name)
QString storeName = name.mid(0, n);
QString objectName = name.mid(n + 1);
QCA::KeyStore store(getKeyStore(storeName));
QCA::KeyStoreManager ksm;
QCA::KeyStore store(getKeyStore(storeName), &ksm);
if(!store.isValid())
{
printf("no such store\n");
@ -659,7 +662,8 @@ static QCA::PGPKey getPGPPublicKey(const QString &name)
QString storeName = name.mid(0, n);
QString objectName = name.mid(n + 1);
QCA::KeyStore store(getKeyStore(storeName));
QCA::KeyStoreManager ksm;
QCA::KeyStore store(getKeyStore(storeName), &ksm);
if(!store.isValid())
{
printf("no such store\n");
@ -699,7 +703,8 @@ static QCA::Certificate getCertificate(const QString &name)
QString storeName = name.mid(0, n);
QString objectName = name.mid(n + 1);
QCA::KeyStore store(getKeyStore(storeName));
QCA::KeyStoreManager ksm;
QCA::KeyStore store(getKeyStore(storeName), &ksm);
if(!store.isValid())
{
printf("no such store\n");
@ -740,7 +745,8 @@ static QCA::PrivateKey getPrivateKey(const QString &name)
QString storeName = name.mid(0, n);
QString objectName = name.mid(n + 1);
QCA::KeyStore store(getKeyStore(storeName));
QCA::KeyStoreManager ksm;
QCA::KeyStore store(getKeyStore(storeName), &ksm);
if(!store.isValid())
{
printf("no such store\n");
@ -806,8 +812,10 @@ static void usage()
printf(" --pgp decrypt [encryptedfile]\n");
printf("\n");
printf(" --list-tlsciphers\n");
printf(" --showentry [keystoreentry id]\n");
printf("\n");
// TODO: showentry?
/*printf("qcatool: simple qca utility\n");
printf("usage: qcatool (--pass, --noprompt) [command]\n");
printf("\n");
@ -958,8 +966,13 @@ int main(int argc, char **argv)
}
// activate the KeyStoreManager and block until ready
QCA::keyStoreManager()->start();
QCA::keyStoreManager()->waitForBusyFinished();
QCA::KeyStoreManager::start();
{
QCA::KeyStoreManager ksm;
ksm.waitForBusyFinished();
}
//QCA::keyStoreManager()->start();
//QCA::keyStoreManager()->waitForBusyFinished();
// hook a passphrase prompt onto all the KeyStores
PassphrasePrompt passphrasePrompt;
@ -2031,11 +2044,12 @@ int main(int argc, char **argv)
}
else if(args[0] == "--list-keystores")
{
QCA::KeyStoreManager *ksm = QCA::keyStoreManager();
QStringList storeList = ksm->keyStores();
//QCA::KeyStoreManager *ksm = QCA::keyStoreManager();
QCA::KeyStoreManager ksm;
QStringList storeList = ksm.keyStores();
for(int n = 0; n < storeList.count(); ++n)
{
QCA::KeyStore ks(storeList[n]);
QCA::KeyStore ks(storeList[n], &ksm);
QString type;
switch(ks.type())
{
@ -2057,7 +2071,8 @@ int main(int argc, char **argv)
return 1;
}
QCA::KeyStore store(getKeyStore(args[1]));
QCA::KeyStoreManager ksm;
QCA::KeyStore store(getKeyStore(args[1]), &ksm);
if(!store.isValid())
{
printf("no such store\n");
@ -2334,6 +2349,35 @@ int main(int argc, char **argv)
cipherList = QCA::TLS::supportedCipherSuites(QCA::TLS::SSL_v2).join("\n\t");
printf("SSL version 2: \n\t%s\n", qPrintable(cipherList));
}
else if(args[0] == "--showentry")
{
if(args.count() < 2)
usage();
else
{
QCA::KeyStoreEntry entry(args[1]);
if(entry.isNull())
{
printf("Entry id is unknown to any provider.\n");
return 1;
}
QString type;
switch(entry.type())
{
case QCA::KeyStoreEntry::TypeKeyBundle: type = "Key "; break;
case QCA::KeyStoreEntry::TypeCertificate: type = "Cert"; break;
case QCA::KeyStoreEntry::TypeCRL: type = "CRL "; break;
case QCA::KeyStoreEntry::TypePGPSecretKey: type = "PSec"; break;
case QCA::KeyStoreEntry::TypePGPPublicKey: type = "PPub"; break;
}
printf("Entry:\n");
printf(" Name: %s\n", qPrintable(entry.name()));
printf(" Type: %s\n", qPrintable(type));
printf(" Store Name: %s\n", qPrintable(entry.storeName()));
printf(" Store Id: %s\n", qPrintable(entry.storeId()));
}
}
else
{
usage();