From f47b2a9f131c1e8c51e5ed00a52eda055e9948dc Mon Sep 17 00:00:00 2001 From: Justin Karneges Date: Thu, 7 Jul 2005 00:53:54 +0000 Subject: [PATCH] simple gpg plugin for now svn path=/trunk/kdesupport/qca/; revision=432337 --- plugins/qca-gnupg/qca-gnupg.cpp | 519 ++++++++++++++++++++++++++++++++ plugins/qca-gnupg/qca-gnupg.pro | 28 ++ 2 files changed, 547 insertions(+) create mode 100644 plugins/qca-gnupg/qca-gnupg.cpp create mode 100644 plugins/qca-gnupg/qca-gnupg.pro diff --git a/plugins/qca-gnupg/qca-gnupg.cpp b/plugins/qca-gnupg/qca-gnupg.cpp new file mode 100644 index 00000000..6fe8dd14 --- /dev/null +++ b/plugins/qca-gnupg/qca-gnupg.cpp @@ -0,0 +1,519 @@ +/* + * Copyright (C) 2003-2005 Justin Karneges + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#ifdef Q_OS_WIN +# include +#endif +#include "gpgop.h" + +#ifdef Q_OS_WIN +static QString find_reg_gpgProgram() +{ + HKEY root; + root = HKEY_CURRENT_USER; + + HKEY hkey; + const char *path = "Software\\GNU\\GnuPG"; + if(RegOpenKeyExA(HKEY_CURRENT_USER, path, 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) + { + if(RegOpenKeyExA(HKEY_LOCAL_MACHINE, path, 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) + return QString::null; + } + + char szValue[256]; + DWORD dwLen = 256; + if(RegQueryValueExA(hkey, "gpgProgram", NULL, NULL, (LPBYTE)szValue, &dwLen) != ERROR_SUCCESS) + { + RegCloseKey(hkey); + return QString::null; + } + + RegCloseKey(hkey); + return QString::fromLatin1(szValue); +} +#endif + +static QString find_bin() +{ + QString bin = "gpg"; +#ifdef Q_OS_WIN + QString s = find_reg_gpgProgram(); + if(!s.isNull()) + bin = s; +#endif + return bin; +} + +using namespace QCA; + +namespace gpgQCAPlugin { + +class MyPGPKeyContext : public PGPKeyContext +{ +public: + PGPKeyContextProps _props; + + MyPGPKeyContext(Provider *p) : PGPKeyContext(p) + { + } + + virtual Provider::Context *clone() const + { + return new MyPGPKeyContext(*this); + } + + virtual const PGPKeyContextProps *props() const + { + return &_props; + } + + virtual QSecureArray toBinary() const + { + // TODO + return QSecureArray(); + } + + virtual QString toAscii() const + { + // TODO + return QString(); + } + + virtual ConvertResult fromBinary(const QSecureArray &a) + { + // TODO + Q_UNUSED(a); + return ErrorDecode; + } + + virtual ConvertResult fromAscii(const QString &s) + { + // TODO + Q_UNUSED(s); + return ErrorDecode; + } +}; + +class MyKeyStoreEntry : public KeyStoreEntryContext +{ +public: + KeyStoreEntry::Type item_type; + PGPKey pub, sec; + + MyKeyStoreEntry(const PGPKey &_pub, const PGPKey &_sec, Provider *p) : KeyStoreEntryContext(p) + { + pub = _pub; + sec = _sec; + if(!sec.isNull()) + item_type = KeyStoreEntry::TypePGPSecretKey; + else + item_type = KeyStoreEntry::TypePGPPublicKey; + } + + MyKeyStoreEntry(const MyKeyStoreEntry &from) : KeyStoreEntryContext(from) + { + } + + ~MyKeyStoreEntry() + { + } + + virtual Provider::Context *clone() const + { + return new MyKeyStoreEntry(*this); + } + + virtual KeyStoreEntry::Type type() const + { + return item_type; + } + + virtual QString name() const + { + return pub.primaryUserId(); + } + + virtual QString id() const + { + return pub.keyId(); + } + + virtual PGPKey pgpSecretKey() const + { + return sec; + } + + virtual PGPKey pgpPublicKey() const + { + return pub; + } +}; + +class MyMessageContext; + +GpgOp *global_gpg; + +class MyKeyStore : public KeyStoreContext +{ + Q_OBJECT +public: + friend class MyMessageContext; + + MyKeyStore(Provider *p) : KeyStoreContext(p) {} + + virtual Provider::Context *clone() const + { + return 0; + } + + virtual int contextId() const + { + // TODO + return 0; // there is only 1 context, so this can be static + } + + virtual QString deviceId() const + { + // TODO + return "qca-gnupg-(gpg)"; + } + + virtual KeyStore::Type type() const + { + return KeyStore::PGPKeyring; + } + + virtual QString name() const + { + return "GnuPG Keyring"; + } + + virtual QList entryList() const + { + QList out; + + GpgOp::KeyList seckeys; + { + GpgOp gpg(find_bin()); + gpg.doSecretKeys(); + while(1) + { + GpgOp::Event e = gpg.waitForEvent(-1); + if(e.type == GpgOp::Event::Finished) + break; + } + if(!gpg.success()) + return out; + seckeys = gpg.keys(); + } + + GpgOp::KeyList pubkeys; + { + GpgOp gpg(find_bin()); + gpg.doPublicKeys(); + while(1) + { + GpgOp::Event e = gpg.waitForEvent(-1); + if(e.type == GpgOp::Event::Finished) + break; + } + if(!gpg.success()) + return out; + pubkeys = gpg.keys(); + } + + for(int n = 0; n < pubkeys.count(); ++n) + { + QString id = pubkeys[n].keyItems.first().id; + MyPGPKeyContext *kc = new MyPGPKeyContext(provider()); + kc->_props.keyId = id; + kc->_props.userIds = QStringList() << pubkeys[n].userIds.first(); + PGPKey pub, sec; + pub.change(kc); + for(int i = 0; i < seckeys.count(); ++i) + { + if(seckeys[i].keyItems.first().id == id) + { + MyPGPKeyContext *kc = new MyPGPKeyContext(provider()); + kc->_props.keyId = id; + kc->_props.userIds = QStringList() << pubkeys[n].userIds.first(); + sec.change(kc); + } + } + + MyKeyStoreEntry *c = new MyKeyStoreEntry(pub, sec, provider()); + out.append(c); + } + + return out; + } + + virtual QList entryTypes() const + { + QList list; + list += KeyStoreEntry::TypePGPSecretKey; + list += KeyStoreEntry::TypePGPPublicKey; + return list; + } + + virtual void submitPassphrase(const QSecureArray &a) + { + global_gpg->submitPassphrase(a.toByteArray()); + } +}; + +class MyKeyStoreList; + +static MyKeyStoreList *keyStoreList = 0; + +class MyKeyStoreList : public KeyStoreListContext +{ + Q_OBJECT +public: + MyKeyStore *ks; + + MyKeyStoreList(Provider *p) : KeyStoreListContext(p) + { + keyStoreList = this; + + ks = 0; + + ks = new MyKeyStore(provider()); + } + + ~MyKeyStoreList() + { + delete ks; + + keyStoreList = 0; + } + + virtual Provider::Context *clone() const + { + return 0; + } + + virtual QList keyStores() const + { + QList list; + if(ks) + list.append(ks); + return list; + } +}; + +class MyOpenPGPContext : public SMSContext +{ +public: + MyOpenPGPContext(Provider *p) : SMSContext(p, "openpgp") + { + // TODO + } + + virtual Provider::Context *clone() const + { + return 0; + } + + virtual MessageContext *createMessage(); +}; + +class MyMessageContext : public MessageContext +{ + Q_OBJECT +public: + MyOpenPGPContext *sms; + + QString signerId; + QByteArray in, out; + bool ok; + + MyMessageContext(MyOpenPGPContext *_sms, Provider *p) : MessageContext(p, "pgpmsg") + { + sms = _sms; + ok = false; + } + + virtual Provider::Context *clone() const + { + return 0; + } + + virtual bool canSignMultiple() const + { + return false; + } + + virtual SecureMessage::Type type() const + { + return SecureMessage::OpenPGP; + } + + virtual void reset() + { + } + + virtual void setupEncrypt(const SecureMessageKeyList &keys) + { + Q_UNUSED(keys); + } + + virtual void setupSign(const SecureMessageKeyList &keys, SecureMessage::SignMode m, bool, bool) + { + signerId = keys.first().pgpSecretKey().keyId(); + Q_UNUSED(m); + } + + virtual void setupVerify(const QByteArray &detachedSig) + { + Q_UNUSED(detachedSig); + } + + virtual void start(SecureMessage::Format f, Operation op) + { + Q_UNUSED(f); + Q_UNUSED(op); + } + + virtual void update(const QByteArray &in) + { + this->in.append(in); + } + + virtual QByteArray read() + { + return out; + } + + virtual void end() + { + GpgOp gpg(find_bin()); + global_gpg = &gpg; + gpg.doSignClearsign(signerId); + gpg.write(in); + gpg.endWrite(); + while(1) + { + GpgOp::Event e = gpg.waitForEvent(-1); + if(e.type == GpgOp::Event::NeedPassphrase) + { + emit keyStoreList->ks->needPassphrase(); + } + else if(e.type == GpgOp::Event::Finished) + break; + } + ok = gpg.success(); + out = gpg.read(); + global_gpg = 0; + } + + virtual bool finished() const + { + // TODO + return true; + } + + virtual void waitForFinished(int msecs) + { + Q_UNUSED(msecs); + } + + virtual bool success() const + { + return ok; + } + + virtual SecureMessage::Error errorCode() const + { + return SecureMessage::ErrorUnknown; + } + + virtual QByteArray signature() const + { + return QByteArray(); + } + + virtual QString hashName() const + { + // TODO + return "sha1"; + } + + virtual SecureMessageSignatureList signers() const + { + return SecureMessageSignatureList(); + } +}; + +MessageContext *MyOpenPGPContext::createMessage() +{ + return new MyMessageContext(this, provider()); +} + +} + +using namespace gpgQCAPlugin; + +class gnupgProvider : public QCA::Provider +{ +public: + virtual void init() + { + } + + virtual QString name() const + { + return "qca-gnupg"; + } + + virtual QStringList features() const + { + QStringList list; + list += "pgpkey"; + list += "openpgp"; + list += "keystorelist"; + return list; + } + + virtual Context *createContext(const QString &type) + { + if(type == "pgpkey") + return new MyPGPKeyContext(this); + else if(type == "openpgp") + return new MyOpenPGPContext(this); + else if(type == "keystorelist") + return new MyKeyStoreList(this); + else + return 0; + } +}; + +class gnupgPlugin : public QCAPlugin +{ + Q_OBJECT +public: + virtual int version() const { return QCA_PLUGIN_VERSION; } + virtual QCA::Provider *createProvider() { return new gnupgProvider; } +}; + +#include "qca-gnupg.moc" + +Q_EXPORT_PLUGIN(gnupgPlugin); diff --git a/plugins/qca-gnupg/qca-gnupg.pro b/plugins/qca-gnupg/qca-gnupg.pro new file mode 100644 index 00000000..e4f9a571 --- /dev/null +++ b/plugins/qca-gnupg/qca-gnupg.pro @@ -0,0 +1,28 @@ +TEMPLATE = lib +CONFIG += plugin +QT -= gui + +#CONFIG += release +CONFIG += debug + +QCA_INC = ../../include/QtCrypto +QCA_LIB = ../.. + +INCLUDEPATH += $$QCA_INC +LIBS += -L$$QCA_LIB -lqca + +windows:LIBS += -ladvapi32 + +GPG_BASE = . +GPGPROC_BASE = $$GPG_BASE/gpgproc +include($$GPGPROC_BASE/gpgproc.pri) +INCLUDEPATH += $$GPGPROC_BASE +INCLUDEPATH += $$GPG_BASE +HEADERS += \ + $$GPG_BASE/gpgop.h +SOURCES += \ + $$GPG_BASE/gpgop.cpp \ + $$GPG_BASE/qca-gnupg.cpp + +#include(conf.pri) +#include(extra.pri)