From 2f702b74ee8c5cf8f4b02355e226d04d5758f53b Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Thu, 23 Nov 2017 00:22:39 +0100 Subject: Prepared crypto --- framework/src/domain/mime/mailcrypto.cpp | 121 +++++++++++++++++-------------- framework/src/domain/mime/mailcrypto.h | 3 +- 2 files changed, 68 insertions(+), 56 deletions(-) diff --git a/framework/src/domain/mime/mailcrypto.cpp b/framework/src/domain/mime/mailcrypto.cpp index 19e81b4f..bdfa2a74 100644 --- a/framework/src/domain/mime/mailcrypto.cpp +++ b/framework/src/domain/mime/mailcrypto.cpp @@ -22,9 +22,12 @@ #include "mailcrypto.h" #include #include +#include +#include #include #include #include +#include #include #include @@ -335,44 +338,12 @@ KMime::Content *composeHeadersAndBody(KMime::Content *orig, QByteArray encodedBo // } // } -//Hardcoded OpenPGPGMIMEFormat for now -KMime::Content *MailCrypto::sign(KMime::Content *content, const std::vector &signers) +// replace simple LFs by CRLFs for all MIME supporting CryptPlugs +// according to RfC 2633, 3.1.1 Canonicalization +static QByteArray canonicalizeContent(KMime::Content *content) { - - // if setContent hasn't been called, we assume that a subjob was added - // and we want to use that - // if (!d->content) { - // Q_ASSERT(d->subjobContents.size() == 1); - // d->content = d->subjobContents.first(); - // } - - //d->resultContent = new KMime::Content; - - // const QGpgME::Protocol *proto = nullptr; - // if (d->format & Kleo::AnyOpenPGP) { - // proto = QGpgME::openpgp(); - // } else if (d->format & Kleo::AnySMIME) { - // proto = QGpgME::smime(); - // } - - const QGpgME::Protocol *proto = QGpgME::openpgp(); - Q_ASSERT(proto); - - qDebug() << "creating signJob from:" << proto->name() << proto->displayName(); - // std::unique_ptr job(proto->signJob(!d->binaryHint(d->format), d->format == Kleo::InlineOpenPGPFormat)); - bool armor = true; - bool textMode = false; - std::unique_ptr job(proto->signJob(armor, textMode)); - // for now just do the main recipients - QByteArray signature; - - content->assemble(); - - // replace simple LFs by CRLFs for all MIME supporting CryptPlugs - // according to RfC 2633, 3.1.1 Canonicalization - QByteArray contentData; // if (d->format & Kleo::InlineOpenPGPFormat) { - // content = d->content->body(); + // return d->content->body(); // } else if (!(d->format & Kleo::SMIMEOpaqueFormat)) { // replace "From " and "--" at the beginning of lines @@ -425,33 +396,73 @@ KMime::Content *MailCrypto::sign(KMime::Content *content, const std::vectorencodedContent()); + return KMime::LFtoCRLF(content->encodedContent()); // } else { // SMimeOpaque doesn't need LFtoCRLF, else it gets munged - // contentData = content->encodedContent(); + // return content->encodedContent(); // } - auto signingMode = GpgME::Detached; +} - // FIXME: Make this async - GpgME::SigningResult res = job->exec(signers, - contentData, - signingMode, - signature); +KMime::Content *MailCrypto::processCrypto(KMime::Content *content, const std::vector &signingKeys, const std::vector &encryptionKeys, MailCrypto::Protocol protocol) +{ + const QGpgME::Protocol *const proto = protocol == MailCrypto::SMIME ? QGpgME::smime() : QGpgME::openpgp(); + Q_ASSERT(proto); - // exec'ed jobs don't delete themselves - job->deleteLater(); + qDebug() << "creating signJob from:" << proto->name() << proto->displayName(); + // for now just do the main recipients + + content->assemble(); - if (res.error().code()) { - qWarning() << "signing failed:" << res.error().asString(); - // job->showErrorDialog( globalPart()->parentWidgetForGui() ); - // setError(res.error().code()); - // setErrorText(QString::fromLocal8Bit(res.error().asString())); + auto signingMode = GpgME::Detached; + bool armor = true; + bool textMode = false; + const bool sign = !signingKeys.empty(); + const bool encrypt = !encryptionKeys.empty(); + + QByteArray resultContent; + QByteArray hashAlgo; + //Trust provided keys and don't check them for validity + bool alwaysTrust = true; + if (sign && encrypt) { + std::unique_ptr job(proto->signEncryptJob(armor, textMode)); + const auto res = job->exec(signingKeys, encryptionKeys, canonicalizeContent(content), alwaysTrust, resultContent); + if (res.first.error().code()) { + qWarning() << "Signing failed:" << res.first.error().asString(); + return nullptr; + } else { + hashAlgo = res.first.createdSignature(0).hashAlgorithmAsString(); + } + if (res.second.error().code()) { + qWarning() << "Encryption failed:" << res.second.error().asString(); + return nullptr; + } + } else if (sign) { + std::unique_ptr job(proto->signJob(armor, textMode)); + auto result = job->exec(signingKeys, canonicalizeContent(content), signingMode, resultContent); + if (result.error().code()) { + qWarning() << "Signing failed:" << result.error().asString(); + return nullptr; + } + hashAlgo = result.createdSignature(0).hashAlgorithmAsString(); + } else if (encrypt) { + std::unique_ptr job(proto->encryptJob(armor, textMode)); + const auto result = job->exec(encryptionKeys, canonicalizeContent(content), alwaysTrust, resultContent); + if (result.error().code()) { + qWarning() << "Encryption failed:" << result.error().asString(); + return nullptr; + } + hashAlgo = "pgp-sha1"; } else { - QByteArray signatureHashAlgo = res.createdSignature(0).hashAlgorithmAsString(); - bool sign = true; - return composeHeadersAndBody(content, signature, sign, signatureHashAlgo); + qWarning() << "Not signing or encrypting"; + return nullptr; } - return nullptr; + + return composeHeadersAndBody(content, resultContent, sign, hashAlgo); +} + +KMime::Content *MailCrypto::sign(KMime::Content *content, const std::vector &signers) +{ + return processCrypto(content, signers, {}, OPENPGP); } std::vector MailCrypto::findKeys(const QStringList &filter, bool findPrivate, Protocol protocol) diff --git a/framework/src/domain/mime/mailcrypto.h b/framework/src/domain/mime/mailcrypto.h index badf1005..ed362ddc 100644 --- a/framework/src/domain/mime/mailcrypto.h +++ b/framework/src/domain/mime/mailcrypto.h @@ -30,6 +30,7 @@ namespace MailCrypto OPENPGP, SMIME }; + KMime::Content *processCrypto(KMime::Content *content, const std::vector &signingKeys, const std::vector &encryptionKeys, MailCrypto::Protocol protocol); KMime::Content *sign(KMime::Content *content, const std::vector &signers); - std::vector findKeys(const QStringList &filter, bool findPrivate = false, Protocol protocol = OPENPGP); + std::vector findKeys(const QStringList &filter, bool findPrivate = false, Protocol protocol = OPENPGP); }; -- cgit v1.2.3