From ae20f0a057f4740e3eedb1641d99c37601ad0b7f Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Thu, 26 Apr 2018 16:43:00 +0200 Subject: No more direct GpgMe usage in the interfaces. --- framework/src/domain/composercontroller.cpp | 32 +++---- framework/src/domain/composercontroller.h | 7 +- framework/src/domain/mime/mailcrypto.cpp | 99 +++++++++++++--------- framework/src/domain/mime/mailcrypto.h | 23 +++-- framework/src/domain/mime/mailtemplates.cpp | 4 +- framework/src/domain/mime/mailtemplates.h | 4 +- .../src/domain/mime/tests/mailtemplatetest.cpp | 50 +---------- 7 files changed, 100 insertions(+), 119 deletions(-) diff --git a/framework/src/domain/composercontroller.cpp b/framework/src/domain/composercontroller.cpp index a71e66f9..fc436003 100644 --- a/framework/src/domain/composercontroller.cpp +++ b/framework/src/domain/composercontroller.cpp @@ -36,7 +36,7 @@ #include "mime/mailcrypto.h" #include "async.h" -std::vector &operator+=(std::vector &list, const std::vector &add) +std::vector &operator+=(std::vector &list, const std::vector &add) { list.insert(std::end(list), std::begin(add), std::end(add)); return list; @@ -133,16 +133,16 @@ public: mb.fromUnicodeString(addressee); SinkLog() << "Searching key for: " << mb.address(); - asyncRun>(this, + asyncRun>(this, [mb] { return MailCrypto::findKeys(QStringList{} << mb.address(), false, false); }, - [this, addressee, id](const std::vector &keys) { + [this, addressee, id](const std::vector &keys) { if (!keys.empty()) { if (keys.size() > 1) { SinkWarning() << "Found more than one key, encrypting to all of them."; } - SinkLog() << "Found key: " << keys.front().primaryFingerprint(); + SinkLog() << "Found key: " << keys.front(); setValue(id, "keyFound", true); setValue(id, "key", QVariant::fromValue(keys)); mMissingKeys.remove(id); @@ -227,10 +227,10 @@ void ComposerController::findPersonalKey() { auto identity = getIdentity(); SinkLog() << "Looking for personal key for: " << identity.address(); - asyncRun>(this, [=] { + asyncRun>(this, [=] { return MailCrypto::findKeys(QStringList{} << identity.address(), true); }, - [this](const std::vector &keys) { + [this](const std::vector &keys) { if (keys.empty()) { SinkWarning() << "Failed to find a personal key."; } else if (keys.size() > 1) { @@ -419,23 +419,23 @@ void ComposerController::recordForAutocompletion(const QByteArray &addrSpec, con } } -std::vector ComposerController::getRecipientKeys() +std::vector ComposerController::getRecipientKeys() { - std::vector keys; + std::vector keys; { - const auto list = toController()->getList>("key"); + const auto list = toController()->getList>("key"); for (const auto &l: list) { keys.insert(std::end(keys), std::begin(l), std::end(l)); } } { - const auto list = ccController()->getList>("key"); + const auto list = ccController()->getList>("key"); for (const auto &l: list) { keys.insert(std::end(keys), std::begin(l), std::end(l)); } } { - const auto list = bccController()->getList>("key"); + const auto list = bccController()->getList>("key"); for (const auto &l: list) { keys.insert(std::end(keys), std::begin(l), std::end(l)); } @@ -463,17 +463,17 @@ KMime::Message::Ptr ComposerController::assembleMessage() }; }); - GpgME::Key attachedKey; - std::vector signingKeys; + MailCrypto::Key attachedKey; + std::vector signingKeys; if (getSign()) { - signingKeys = getPersonalKeys().value>(); + signingKeys = getPersonalKeys().value>(); Q_ASSERT(!signingKeys.empty()); attachedKey = signingKeys[0]; } - std::vector encryptionKeys; + std::vector encryptionKeys; if (getEncrypt()) { //Encrypt to self so we can read the sent message - auto personalKeys = getPersonalKeys().value>(); + auto personalKeys = getPersonalKeys().value>(); attachedKey = personalKeys[0]; diff --git a/framework/src/domain/composercontroller.h b/framework/src/domain/composercontroller.h index ac83dfd3..17271dce 100644 --- a/framework/src/domain/composercontroller.h +++ b/framework/src/domain/composercontroller.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include "completer.h" #include "selector.h" @@ -39,7 +39,6 @@ inline bool operator !=(const KMime::Types::Mailbox &l, const KMime::Types::Mail Q_DECLARE_METATYPE(KMime::Types::Mailbox); -Q_DECLARE_METATYPE(GpgME::Key); namespace KMime { class Message; @@ -66,7 +65,7 @@ class ComposerController : public Kube::Controller KUBE_CONTROLLER_PROPERTY(KMime::Message::Ptr, ExistingMessage, existingMessage) KUBE_CONTROLLER_PROPERTY(Sink::ApplicationDomain::Mail, ExistingMail, existingMail) - KUBE_CONTROLLER_PROPERTY(/*std::vector*/QVariant, PersonalKeys, personalKeys) + KUBE_CONTROLLER_PROPERTY(/*std::vector*/QVariant, PersonalKeys, personalKeys) KUBE_CONTROLLER_PROPERTY(bool, FoundPersonalKeys, foundPersonalKeys) KUBE_CONTROLLER_LISTCONTROLLER(to) @@ -110,7 +109,7 @@ private: void setMessage(const QSharedPointer &msg); void addAttachmentPart(KMime::Content *partToAttach); KMime::Message::Ptr assembleMessage(); - std::vector getRecipientKeys(); + std::vector getRecipientKeys(); QScopedPointer mRecipientCompleter; QScopedPointer mIdentitySelector; diff --git a/framework/src/domain/mime/mailcrypto.cpp b/framework/src/domain/mime/mailcrypto.cpp index da1b82c7..a7f3772a 100644 --- a/framework/src/domain/mime/mailcrypto.cpp +++ b/framework/src/domain/mime/mailcrypto.cpp @@ -44,6 +44,21 @@ #include #include +using namespace MailCrypto; + +QDebug operator<< (QDebug d, const MailCrypto::Key &key) +{ + d << key.key.primaryFingerprint(); + return d; +} + +static std::vector toGpgME(const std::vector keys) +{ + std::vector list; + std::transform(keys.begin(), keys.end(), std::back_inserter(list), [] (const Key &key) { return key.key; }); + return list; +} + // replace simple LFs by CRLFs for all MIME supporting CryptPlugs // according to RfC 2633, 3.1.1 Canonicalization static QByteArray canonicalizeContent(KMime::Content *content) @@ -112,7 +127,7 @@ static QByteArray canonicalizeContent(KMime::Content *content) /** * Get the given `key` in the armor format. */ -Expected exportPublicKey(const GpgME::Key &key) +Expected exportPublicKey(const Key &key) { // Not using the Qt API because it apparently blocks (the `result` signal is never // triggered) @@ -122,11 +137,11 @@ Expected exportPublicKey(const GpgME::Key &key) QGpgME::QByteArrayDataProvider dp; GpgME::Data data(&dp); - qDebug() << "Exporting public key:" << key.shortKeyID(); - auto error = ctx->exportPublicKeys(key.keyID(), data); + qDebug() << "Exporting public key:" << key.key.shortKeyID(); + auto error = ctx->exportPublicKeys(key.key.keyID(), data); if (error.code()) { - return makeUnexpected(error); + return makeUnexpected(Error{error}); } return dp.data(); @@ -143,14 +158,14 @@ Expected exportPublicKey(const GpgME::Key &key) * * Used by the `createSignedEmail` and `createEncryptedEmail` functions. */ -Expected> -appendPublicKey(std::unique_ptr msg, const GpgME::Key &key) +Expected> +appendPublicKey(std::unique_ptr msg, const Key &key) { const auto publicKeyExportResult = exportPublicKey(key); if (!publicKeyExportResult) { // "Could not export public key" - return makeUnexpected(publicKeyExportResult.error()); + return makeUnexpected(Error{publicKeyExportResult.error()}); } const auto publicKeyData = publicKeyExportResult.value(); @@ -163,7 +178,7 @@ appendPublicKey(std::unique_ptr msg, const GpgME::Key &key) { keyAttachment->contentType()->setMimeType("application/pgp-keys"); keyAttachment->contentDisposition()->setDisposition(KMime::Headers::CDattachment); - keyAttachment->contentDisposition()->setFilename(QString("0x") + key.shortKeyID() + ".asc"); + keyAttachment->contentDisposition()->setFilename(QString("0x") + key.key.shortKeyID() + ".asc"); keyAttachment->setBody(publicKeyData); } @@ -177,39 +192,39 @@ appendPublicKey(std::unique_ptr msg, const GpgME::Key &key) return result; } -Expected encrypt(const QByteArray &content, const std::vector &encryptionKeys) +Expected encrypt(const QByteArray &content, const std::vector &encryptionKeys) { QByteArray resultData; const QGpgME::Protocol *const proto = QGpgME::openpgp(); std::unique_ptr job(proto->encryptJob(/* armor = */ true)); - const auto result = job->exec(encryptionKeys, content, /* alwaysTrust = */ true, resultData); + const auto result = job->exec(toGpgME(encryptionKeys), content, /* alwaysTrust = */ true, resultData); if (result.error().code()) { qWarning() << "Encryption failed:" << result.error().asString(); - return makeUnexpected(result.error()); + return makeUnexpected(Error{result.error()}); } return resultData; } -Expected signAndEncrypt(const QByteArray &content, - const std::vector &signingKeys, const std::vector &encryptionKeys) +Expected signAndEncrypt(const QByteArray &content, + const std::vector &signingKeys, const std::vector &encryptionKeys) { QByteArray resultData; const QGpgME::Protocol *const proto = QGpgME::openpgp(); std::unique_ptr job(proto->signEncryptJob(/* armor = */ true)); - const auto result = job->exec(signingKeys, encryptionKeys, content, /* alwaysTrust = */ true, resultData); + const auto result = job->exec(toGpgME(signingKeys), toGpgME(encryptionKeys), content, /* alwaysTrust = */ true, resultData); if (result.first.error().code()) { qWarning() << "Signing failed:" << result.first.error().asString(); - return makeUnexpected(result.first.error()); + return makeUnexpected(Error{result.first.error()}); } if (result.second.error().code()) { qWarning() << "Encryption failed:" << result.second.error().asString(); - return makeUnexpected(result.second.error()); + return makeUnexpected(Error{result.second.error()}); } return resultData; @@ -276,9 +291,9 @@ std::unique_ptr createEncryptedPart(QByteArray encryptedData) * - `application/pgp-keys` (the public key as attachment, which is the first of the * `signingKeys`) */ -Expected> -createEncryptedEmail(KMime::Content *content, const std::vector &encryptionKeys, - const GpgME::Key &attachedKey, const std::vector &signingKeys = {}) +Expected> +createEncryptedEmail(KMime::Content *content, const std::vector &encryptionKeys, + const Key &attachedKey, const std::vector &signingKeys = {}) { auto contentToEncrypt = canonicalizeContent(content); @@ -287,7 +302,7 @@ createEncryptedEmail(KMime::Content *content, const std::vector &enc signAndEncrypt(contentToEncrypt, signingKeys, encryptionKeys); if (!encryptionResult) { - return makeUnexpected(encryptionResult.error()); + return makeUnexpected(Error{encryptionResult.error()}); } auto encryptedPart = createEncryptedPart(encryptionResult.value()); @@ -305,18 +320,18 @@ createEncryptedEmail(KMime::Content *content, const std::vector &enc * Sign the given content and returns the signing data and the algorithm used * for integrity check in the "pgp-" format. */ -Expected> -sign(const QByteArray &content, const std::vector &signingKeys) +Expected> +sign(const QByteArray &content, const std::vector &signingKeys) { QByteArray resultData; const QGpgME::Protocol *const proto = QGpgME::openpgp(); std::unique_ptr job(proto->signJob(/* armor = */ true)); - const auto result = job->exec(signingKeys, content, GpgME::Detached, resultData); + const auto result = job->exec(toGpgME(signingKeys), content, GpgME::Detached, resultData); if (result.error().code()) { qWarning() << "Signing failed:" << result.error().asString(); - return makeUnexpected(result.error()); + return makeUnexpected(Error{result.error()}); } auto algo = result.createdSignature(0).hashAlgorithmAsString(); @@ -380,9 +395,9 @@ std::unique_ptr createSignedPart( * - `application/pgp-keys` (the public key as attachment, which is the first of the * `signingKeys`) */ -Expected> +Expected> createSignedEmail(std::unique_ptr content, - const std::vector &signingKeys, const GpgME::Key &attachedKey) + const std::vector &signingKeys, const Key &attachedKey) { Q_ASSERT(!signingKeys.empty()); @@ -391,7 +406,7 @@ createSignedEmail(std::unique_ptr content, auto signingResult = sign(contentToSign, signingKeys); if (!signingResult) { - return makeUnexpected(signingResult.error()); + return makeUnexpected(Error{signingResult.error()}); } QByteArray signingData; @@ -409,9 +424,9 @@ createSignedEmail(std::unique_ptr content, return publicKeyAppendResult; } -Expected> -MailCrypto::processCrypto(std::unique_ptr content, const std::vector &signingKeys, - const std::vector &encryptionKeys, const GpgME::Key &attachedKey) +Expected> +MailCrypto::processCrypto(std::unique_ptr content, const std::vector &signingKeys, + const std::vector &encryptionKeys, const Key &attachedKey) { if (!encryptionKeys.empty()) { return createEncryptedEmail(content.release(), encryptionKeys, attachedKey, signingKeys); @@ -423,12 +438,12 @@ MailCrypto::processCrypto(std::unique_ptr content, const std::ve } } -void MailCrypto::importKeys(const std::vector &keys) +void MailCrypto::importKeys(const std::vector &keys) { const QGpgME::Protocol *const backend = QGpgME::openpgp(); Q_ASSERT(backend); auto *job = backend->importFromKeyserverJob(); - job->exec(keys); + job->exec(toGpgME(keys)); } MailCrypto::ImportResult MailCrypto::importKey(const QByteArray &pkey) @@ -439,7 +454,7 @@ MailCrypto::ImportResult MailCrypto::importKey(const QByteArray &pkey) return {result.numConsidered(), result.numImported(), result.numUnchanged()}; } -static GpgME::KeyListResult listKeys(const QStringList &patterns, bool secretOnly, int keyListMode, std::vector &keys) +static GpgME::KeyListResult listKeys(const QStringList &patterns, bool secretOnly, int keyListMode, std::vector &keys) { QByteArrayList list; std::transform(patterns.constBegin(), patterns.constEnd(), std::back_inserter(list), [] (const QString &s) { return s.toUtf8(); }); @@ -456,7 +471,7 @@ static GpgME::KeyListResult listKeys(const QStringList &patterns, bool secretOnl GpgME::Error err; do { - keys.push_back( ctx->nextKey(err)); + keys.push_back( Key{ctx->nextKey(err)}); } while ( !err ); keys.pop_back(); @@ -466,21 +481,21 @@ static GpgME::KeyListResult listKeys(const QStringList &patterns, bool secretOnl return result; } -std::vector MailCrypto::findKeys(const QStringList &filter, bool findPrivate, bool remote) +std::vector MailCrypto::findKeys(const QStringList &filter, bool findPrivate, bool remote) { - std::vector keys; + std::vector keys; GpgME::KeyListResult res = listKeys(filter, findPrivate, remote ? GpgME::Extern : GpgME::Local, keys); if (res.error()) { qWarning() << "Failed to lookup keys: " << res.error().asString(); - return keys; + return {}; } qWarning() << "got keys:" << keys.size(); - for (std::vector< GpgME::Key >::iterator i = keys.begin(); i != keys.end(); ++i) { - qWarning() << "key isnull:" << i->isNull() << "isexpired:" << i->isExpired(); - qWarning() << "key numuserIds:" << i->numUserIDs(); - for (uint k = 0; k < i->numUserIDs(); ++k) { - qWarning() << "userIDs:" << i->userID(k).email(); + for (auto i = keys.begin(); i != keys.end(); ++i) { + qWarning() << "key isnull:" << i->key.isNull() << "isexpired:" << i->key.isExpired(); + qWarning() << "key numuserIds:" << i->key.numUserIDs(); + for (uint k = 0; k < i->key.numUserIDs(); ++k) { + qWarning() << "userIDs:" << i->key.userID(k).email(); } } diff --git a/framework/src/domain/mime/mailcrypto.h b/framework/src/domain/mime/mailcrypto.h index 9e317b43..c9247859 100644 --- a/framework/src/domain/mime/mailcrypto.h +++ b/framework/src/domain/mime/mailcrypto.h @@ -25,19 +25,28 @@ #include #include +#include #include #include namespace MailCrypto { -Expected> -processCrypto(std::unique_ptr content, const std::vector &signingKeys, - const std::vector &encryptionKeys, const GpgME::Key &attachedKey); +struct Key { + GpgME::Key key; +}; + +struct Error { + GpgME::Error key; +}; -std::vector findKeys(const QStringList &filter, bool findPrivate = false, bool remote = false); +Expected> +processCrypto(std::unique_ptr content, const std::vector &signingKeys, + const std::vector &encryptionKeys, const Key &attachedKey); -void importKeys(const std::vector &keys); +std::vector findKeys(const QStringList &filter, bool findPrivate = false, bool remote = false); + +void importKeys(const std::vector &keys); struct ImportResult { int considered; @@ -48,3 +57,7 @@ struct ImportResult { ImportResult importKey(const QByteArray &key); }; // namespace MailCrypto + +Q_DECLARE_METATYPE(MailCrypto::Key); + +QDebug operator<< (QDebug d, const MailCrypto::Key &); diff --git a/framework/src/domain/mime/mailtemplates.cpp b/framework/src/domain/mime/mailtemplates.cpp index a614da1a..ac2b2b72 100644 --- a/framework/src/domain/mime/mailtemplates.cpp +++ b/framework/src/domain/mime/mailtemplates.cpp @@ -1027,8 +1027,8 @@ static KMime::Types::Mailbox::List stringListToMailboxes(const QStringList &list KMime::Message::Ptr MailTemplates::createMessage(KMime::Message::Ptr existingMessage, const QStringList &to, const QStringList &cc, const QStringList &bcc, const KMime::Types::Mailbox &from, const QString &subject, const QString &body, bool htmlBody, - const QList &attachments, const std::vector &signingKeys, - const std::vector &encryptionKeys, const GpgME::Key &attachedKey) + const QList &attachments, const std::vector &signingKeys, + const std::vector &encryptionKeys, const MailCrypto::Key &attachedKey) { auto mail = existingMessage; if (!mail) { diff --git a/framework/src/domain/mime/mailtemplates.h b/framework/src/domain/mime/mailtemplates.h index 154b76a2..a894d120 100644 --- a/framework/src/domain/mime/mailtemplates.h +++ b/framework/src/domain/mime/mailtemplates.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include struct Attachment { QString name; @@ -38,5 +38,5 @@ namespace MailTemplates void forward(const KMime::Message::Ptr &origMsg, const std::function &callback); QString plaintextContent(const KMime::Message::Ptr &origMsg); QString body(const KMime::Message::Ptr &msg, bool &isHtml); - KMime::Message::Ptr createMessage(KMime::Message::Ptr existingMessage, const QStringList &to, const QStringList &cc, const QStringList &bcc, const KMime::Types::Mailbox &from, const QString &subject, const QString &body, bool htmlBody, const QList &attachments, const std::vector &signingKeys = {}, const std::vector &encryptionKeys = {}, const GpgME::Key &attachedKey = {}); + KMime::Message::Ptr createMessage(KMime::Message::Ptr existingMessage, const QStringList &to, const QStringList &cc, const QStringList &bcc, const KMime::Types::Mailbox &from, const QString &subject, const QString &body, bool htmlBody, const QList &attachments, const std::vector &signingKeys = {}, const std::vector &encryptionKeys = {}, const MailCrypto::Key &attachedKey = {}); }; diff --git a/framework/src/domain/mime/tests/mailtemplatetest.cpp b/framework/src/domain/mime/tests/mailtemplatetest.cpp index d07b704d..75debd75 100644 --- a/framework/src/domain/mime/tests/mailtemplatetest.cpp +++ b/framework/src/domain/mime/tests/mailtemplatetest.cpp @@ -6,10 +6,6 @@ #include #include -#include -#include -#include -#include #include "mailtemplates.h" #include "mailcrypto.h" @@ -24,45 +20,6 @@ static KMime::Content *getSubpart(KMime::Content *msg, const QByteArray &mimeTyp return nullptr; } -static std::vector< GpgME::Key, std::allocator< GpgME::Key > > getKeys(bool smime = false) -{ - QGpgME::KeyListJob *job = nullptr; - - if (smime) { - const QGpgME::Protocol *const backend = QGpgME::smime(); - Q_ASSERT(backend); - job = backend->keyListJob(/* remote = */ false); - } else { - const QGpgME::Protocol *const backend = QGpgME::openpgp(); - Q_ASSERT(backend); - job = backend->keyListJob(/* remote = */ false); - } - Q_ASSERT(job); - - std::vector< GpgME::Key > keys; - GpgME::KeyListResult res = job->exec(QStringList(), /* secretOnly = */ true, keys); - - if (!smime) { - Q_ASSERT(keys.size() == 3); - } - - Q_ASSERT(!res.error()); - - /* - qDebug() << "got private keys:" << keys.size(); - - for (std::vector< GpgME::Key >::iterator i = keys.begin(); i != keys.end(); ++i) { - qDebug() << "key isnull:" << i->isNull() << "isexpired:" << i->isExpired(); - qDebug() << "key numuserIds:" << i->numUserIDs(); - for (uint k = 0; k < i->numUserIDs(); ++k) { - qDebug() << "userIDs:" << i->userID(k).email(); - } - } - */ - - return keys; -} - static QByteArray readMailFromFile(const QString &mailFile) { Q_ASSERT(!QString::fromLatin1(MAIL_DATA_DIR).isEmpty()); @@ -399,8 +356,7 @@ private slots: QString body = "body"; QList attachments; - std::vector keys = getKeys(); - + auto keys = MailCrypto::findKeys({}, true, false); auto result = MailTemplates::createMessage({}, to, cc, bcc, from, subject, body, false, attachments, keys, {}, keys[0]); QVERIFY(result); @@ -442,9 +398,7 @@ private slots: QString body = "body"; QList attachments = {{"name", "filename", "mimetype", true, "inlineAttachment"}, {"name", "filename", "mimetype", false, "nonInlineAttachment"}}; - std::vector keys = getKeys(); - - auto result = MailTemplates::createMessage({}, to, cc, bcc, from, subject, body, false, attachments, keys); + auto result = MailTemplates::createMessage({}, to, cc, bcc, from, subject, body, false, attachments, MailCrypto::findKeys({}, true, false)); QVERIFY(result); QCOMPARE(result->subject()->asUnicodeString(), subject); -- cgit v1.2.3