diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2017-12-11 20:38:09 +0100 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2017-12-11 23:55:32 +0100 |
commit | d5c44099863d0968a0cbf8f10f04ecf3f4e8ff17 (patch) | |
tree | 7f481f96abd47a3a04c40b4fe0d09d9cdf14f00d /framework/src/domain/mime/mimetreeparser/messagepart.cpp | |
parent | 9f2b3626cc3399c47736faa1b9954f7dbdbe8bd6 (diff) | |
download | kube-d5c44099863d0968a0cbf8f10f04ecf3f4e8ff17.tar.gz kube-d5c44099863d0968a0cbf8f10f04ecf3f4e8ff17.zip |
Stop using useless abstractions (that are not even threadsafe)
Diffstat (limited to 'framework/src/domain/mime/mimetreeparser/messagepart.cpp')
-rw-r--r-- | framework/src/domain/mime/mimetreeparser/messagepart.cpp | 207 |
1 files changed, 92 insertions, 115 deletions
diff --git a/framework/src/domain/mime/mimetreeparser/messagepart.cpp b/framework/src/domain/mime/mimetreeparser/messagepart.cpp index fb61e015..3ba19567 100644 --- a/framework/src/domain/mime/mimetreeparser/messagepart.cpp +++ b/framework/src/domain/mime/mimetreeparser/messagepart.cpp | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (c) 2015 Sandro Knauß <sknauss@kde.org> | 2 | Copyright (c) 2015 Sandro Knauß <sknauss@kde.org> |
3 | Copyright (c) 2017 Christian Mollekopf <mollekopf@kolabsys.com> | ||
3 | 4 | ||
4 | This library is free software; you can redistribute it and/or modify it | 5 | This library is free software; you can redistribute it and/or modify it |
5 | under the terms of the GNU Library General Public License as published by | 6 | under the terms of the GNU Library General Public License as published by |
@@ -21,24 +22,17 @@ | |||
21 | #include "mimetreeparser_debug.h" | 22 | #include "mimetreeparser_debug.h" |
22 | #include "cryptohelper.h" | 23 | #include "cryptohelper.h" |
23 | #include "objecttreeparser.h" | 24 | #include "objecttreeparser.h" |
24 | #include "qgpgmejobexecutor.h" | ||
25 | |||
26 | #include "cryptobodypartmemento.h" | ||
27 | #include "decryptverifybodypartmemento.h" | ||
28 | #include "verifydetachedbodypartmemento.h" | ||
29 | #include "verifyopaquebodypartmemento.h" | ||
30 | 25 | ||
31 | #include "utils.h" | 26 | #include "utils.h" |
32 | 27 | ||
33 | #include <KMime/Content> | 28 | #include <KMime/Content> |
34 | 29 | ||
35 | #include <QGpgME/DN> | 30 | #include <QGpgME/DN> |
36 | #include <QGpgME/Protocol> | 31 | #include <QGpgME/DataProvider> |
37 | #include <QGpgME/ImportJob> | ||
38 | #include <QGpgME/KeyListJob> | ||
39 | #include <QGpgME/VerifyDetachedJob> | ||
40 | #include <QGpgME/VerifyOpaqueJob> | ||
41 | 32 | ||
33 | #include <gpgme++/context.h> | ||
34 | #include <gpgme++/data.h> | ||
35 | #include <gpgme++/verificationresult.h> | ||
42 | #include <gpgme++/key.h> | 36 | #include <gpgme++/key.h> |
43 | #include <gpgme++/keylistresult.h> | 37 | #include <gpgme++/keylistresult.h> |
44 | #include <gpgme.h> | 38 | #include <gpgme.h> |
@@ -48,6 +42,24 @@ | |||
48 | 42 | ||
49 | using namespace MimeTreeParser; | 43 | using namespace MimeTreeParser; |
50 | 44 | ||
45 | static GpgME::Data fromBA(const QByteArray &ba) | ||
46 | { | ||
47 | return {ba.data(), static_cast<size_t>(ba.size()), false}; | ||
48 | } | ||
49 | |||
50 | static QSharedPointer<GpgME::Context> gpgContext(GpgME::Protocol protocol) | ||
51 | { | ||
52 | GpgME::initializeLibrary(); | ||
53 | auto error = GpgME::checkEngine(protocol); | ||
54 | if (error) { | ||
55 | qWarning() << "Engine check failed: " << error.asString(); | ||
56 | } | ||
57 | auto ctx = QSharedPointer<GpgME::Context>(GpgME::Context::createForProtocol(protocol)); | ||
58 | Q_ASSERT(ctx); | ||
59 | return ctx; | ||
60 | } | ||
61 | |||
62 | |||
51 | //------MessagePart----------------------- | 63 | //------MessagePart----------------------- |
52 | MessagePart::MessagePart(ObjectTreeParser *otp, const QString &text, KMime::Content *node) | 64 | MessagePart::MessagePart(ObjectTreeParser *otp, const QString &text, KMime::Content *node) |
53 | : mText(text) | 65 | : mText(text) |
@@ -382,7 +394,7 @@ void TextMessagePart::parseContent() | |||
382 | mEncryptionState = KMMsgNotEncrypted; | 394 | mEncryptionState = KMMsgNotEncrypted; |
383 | const auto blocks = prepareMessageForDecryption(mNode->decodedContent()); | 395 | const auto blocks = prepareMessageForDecryption(mNode->decodedContent()); |
384 | 396 | ||
385 | const auto cryptProto = QGpgME::openpgp(); | 397 | const auto cryptProto = GpgME::OpenPGP; |
386 | 398 | ||
387 | if (!blocks.isEmpty()) { | 399 | if (!blocks.isEmpty()) { |
388 | 400 | ||
@@ -639,7 +651,7 @@ QString AlternativeMessagePart::htmlContent() const | |||
639 | 651 | ||
640 | //-----CertMessageBlock---------------------- | 652 | //-----CertMessageBlock---------------------- |
641 | 653 | ||
642 | CertMessagePart::CertMessagePart(ObjectTreeParser *otp, KMime::Content *node, const QGpgME::Protocol *cryptoProto) | 654 | CertMessagePart::CertMessagePart(ObjectTreeParser *otp, KMime::Content *node, const GpgME::Protocol cryptoProto) |
643 | : MessagePart(otp, QString(), node) | 655 | : MessagePart(otp, QString(), node) |
644 | , mCryptoProto(cryptoProto) | 656 | , mCryptoProto(cryptoProto) |
645 | { | 657 | { |
@@ -657,9 +669,8 @@ CertMessagePart::~CertMessagePart() | |||
657 | void CertMessagePart::import() | 669 | void CertMessagePart::import() |
658 | { | 670 | { |
659 | const QByteArray certData = mNode->decodedContent(); | 671 | const QByteArray certData = mNode->decodedContent(); |
660 | QGpgME::ImportJob *import = mCryptoProto->importJob(); | 672 | auto ctx = gpgContext(mCryptoProto); |
661 | QGpgMEJobExecutor executor; | 673 | const auto result = ctx->importKeys(fromBA(certData)); |
662 | auto result = executor.exec(import, certData); | ||
663 | } | 674 | } |
664 | 675 | ||
665 | QString CertMessagePart::text() const | 676 | QString CertMessagePart::text() const |
@@ -670,11 +681,11 @@ QString CertMessagePart::text() const | |||
670 | //-----SignedMessageBlock--------------------- | 681 | //-----SignedMessageBlock--------------------- |
671 | SignedMessagePart::SignedMessagePart(ObjectTreeParser *otp, | 682 | SignedMessagePart::SignedMessagePart(ObjectTreeParser *otp, |
672 | const QString &text, | 683 | const QString &text, |
673 | const QGpgME::Protocol *cryptoProto, | 684 | const GpgME::Protocol cryptoProto, |
674 | const QString &fromAddress, | 685 | const QString &fromAddress, |
675 | KMime::Content *node, KMime::Content *signedData) | 686 | KMime::Content *node, KMime::Content *signedData) |
676 | : MessagePart(otp, text, node) | 687 | : MessagePart(otp, text, node) |
677 | , mCryptoProto(cryptoProto) | 688 | , mProtocol(cryptoProto) |
678 | , mFromAddress(fromAddress) | 689 | , mFromAddress(fromAddress) |
679 | , mSignedData(signedData) | 690 | , mSignedData(signedData) |
680 | { | 691 | { |
@@ -700,20 +711,6 @@ bool SignedMessagePart::isSigned() const | |||
700 | return mMetaData.isSigned; | 711 | return mMetaData.isSigned; |
701 | } | 712 | } |
702 | 713 | ||
703 | CryptoBodyPartMemento *SignedMessagePart::verifySignature(const QByteArray &data, const QByteArray &signature) | ||
704 | { | ||
705 | if (!signature.isEmpty()) { | ||
706 | if (QGpgME::VerifyDetachedJob *job = mCryptoProto->verifyDetachedJob()) { | ||
707 | return new VerifyDetachedBodyPartMemento(job, mCryptoProto->keyListJob(), signature, data); | ||
708 | } | ||
709 | } else { | ||
710 | if (QGpgME::VerifyOpaqueJob *job = mCryptoProto->verifyOpaqueJob()) { | ||
711 | return new VerifyOpaqueBodyPartMemento(job, mCryptoProto->keyListJob(), data); | ||
712 | } | ||
713 | } | ||
714 | return nullptr; | ||
715 | } | ||
716 | |||
717 | static int signatureToStatus(const GpgME::Signature &sig) | 714 | static int signatureToStatus(const GpgME::Signature &sig) |
718 | { | 715 | { |
719 | switch (sig.status().code()) { | 716 | switch (sig.status().code()) { |
@@ -739,6 +736,23 @@ QString prettifyDN(const char *uid) | |||
739 | return QGpgME::DN(uid).prettyDN(); | 736 | return QGpgME::DN(uid).prettyDN(); |
740 | } | 737 | } |
741 | 738 | ||
739 | static GpgME::KeyListResult listKeys(GpgME::Context * ctx, const char *pattern, bool secretOnly, std::vector<GpgME::Key> &keys) { | ||
740 | if (const GpgME::Error err = ctx->startKeyListing(pattern, secretOnly)) { | ||
741 | return GpgME::KeyListResult( 0, err ); | ||
742 | } | ||
743 | |||
744 | GpgME::Error err; | ||
745 | do { | ||
746 | keys.push_back( ctx->nextKey(err)); | ||
747 | } while ( !err ); | ||
748 | |||
749 | keys.pop_back(); | ||
750 | |||
751 | const GpgME::KeyListResult result = ctx->endKeyListing(); | ||
752 | ctx->cancelPendingOperation(); | ||
753 | return result; | ||
754 | } | ||
755 | |||
742 | void SignedMessagePart::sigStatusToMetaData() | 756 | void SignedMessagePart::sigStatusToMetaData() |
743 | { | 757 | { |
744 | GpgME::Key key; | 758 | GpgME::Key key; |
@@ -749,29 +763,22 @@ void SignedMessagePart::sigStatusToMetaData() | |||
749 | mMetaData.sigSummary = signature.summary(); | 763 | mMetaData.sigSummary = signature.summary(); |
750 | 764 | ||
751 | if (mMetaData.isGoodSignature && !key.keyID()) { | 765 | if (mMetaData.isGoodSignature && !key.keyID()) { |
752 | // Search for the key by its fingerprint so that we can check for | 766 | auto ctx = gpgContext(mProtocol); |
753 | // trust etc. | 767 | // Search for the key by its fingerprint so that we can check for trust etc. |
754 | QGpgME::KeyListJob *job = mCryptoProto->keyListJob(false); // local, no sigs | 768 | std::vector<GpgME::Key> found_keys; |
755 | if (!job) { | 769 | auto res = listKeys(ctx.data(), signature.fingerprint(), false, found_keys); |
756 | qCDebug(MIMETREEPARSER_LOG) << "The Crypto backend does not support listing keys. "; | 770 | if (res.error()) { |
771 | qCDebug(MIMETREEPARSER_LOG) << "Error while searching key for Fingerprint: " << signature.fingerprint(); | ||
772 | } | ||
773 | if (found_keys.size() > 1) { | ||
774 | // Should not happen | ||
775 | qCDebug(MIMETREEPARSER_LOG) << "Oops: Found more then one Key for Fingerprint: " << signature.fingerprint(); | ||
776 | } | ||
777 | if (found_keys.empty()) { | ||
778 | // Should not happen at this point | ||
779 | qCWarning(MIMETREEPARSER_LOG) << "Oops: Found no Key for Fingerprint: " << signature.fingerprint(); | ||
757 | } else { | 780 | } else { |
758 | std::vector<GpgME::Key> found_keys; | 781 | key = found_keys[0]; |
759 | // As we are local it is ok to make this synchronous | ||
760 | GpgME::KeyListResult res = job->exec(QStringList(QLatin1String(signature.fingerprint())), false, found_keys); | ||
761 | if (res.error()) { | ||
762 | qCDebug(MIMETREEPARSER_LOG) << "Error while searching key for Fingerprint: " << signature.fingerprint(); | ||
763 | } | ||
764 | if (found_keys.size() > 1) { | ||
765 | // Should not happen | ||
766 | qCDebug(MIMETREEPARSER_LOG) << "Oops: Found more then one Key for Fingerprint: " << signature.fingerprint(); | ||
767 | } | ||
768 | if (found_keys.empty()) { | ||
769 | // Should not happen at this point | ||
770 | qCWarning(MIMETREEPARSER_LOG) << "Oops: Found no Key for Fingerprint: " << signature.fingerprint(); | ||
771 | } else { | ||
772 | key = found_keys[0]; | ||
773 | } | ||
774 | delete job; | ||
775 | } | 782 | } |
776 | } | 783 | } |
777 | 784 | ||
@@ -857,25 +864,18 @@ void SignedMessagePart::startVerificationDetached(const QByteArray &text, KMime: | |||
857 | mMetaData.status = tr("Wrong Crypto Plug-In."); | 864 | mMetaData.status = tr("Wrong Crypto Plug-In."); |
858 | mMetaData.status_code = GPGME_SIG_STAT_NONE; | 865 | mMetaData.status_code = GPGME_SIG_STAT_NONE; |
859 | 866 | ||
860 | if (auto *m = verifySignature(text, signature)) { | 867 | auto ctx = gpgContext(mProtocol); |
861 | m->exec(); | 868 | |
862 | if (!signature.isEmpty()) { | 869 | if (!signature.isEmpty()) { |
863 | mVerifiedText = text; | 870 | qWarning() << "We have a signature"; |
864 | } | 871 | auto result = ctx->verifyDetachedSignature(fromBA(signature), fromBA(text)); |
865 | setVerificationResult(m, textNode); | 872 | setVerificationResult(result, textNode, text); |
866 | delete m; | ||
867 | } else { | 873 | } else { |
868 | QString errorMsg; | 874 | qWarning() << "We have no signature"; |
869 | if (!mCryptoProto) { | 875 | QGpgME::QByteArrayDataProvider out; |
870 | errorMsg = tr("No appropriate crypto plug-in was found."); | 876 | GpgME::Data outdata(&out); |
871 | } else { | 877 | auto result = ctx->verifyOpaqueSignature(fromBA(text), outdata); |
872 | errorMsg = tr("Crypto plug-in \"%1\" cannot verify signatures.").arg( | 878 | setVerificationResult(result, textNode, out.data()); |
873 | mCryptoProto->name()); | ||
874 | } | ||
875 | mMetaData.errorText = tr("The message is signed, but the " | ||
876 | "validity of the signature cannot be " | ||
877 | "verified.<br />" | ||
878 | "Reason: %1").arg(errorMsg); | ||
879 | } | 879 | } |
880 | 880 | ||
881 | if (!mMetaData.isSigned) { | 881 | if (!mMetaData.isSigned) { |
@@ -883,24 +883,13 @@ void SignedMessagePart::startVerificationDetached(const QByteArray &text, KMime: | |||
883 | } | 883 | } |
884 | } | 884 | } |
885 | 885 | ||
886 | void SignedMessagePart::setVerificationResult(const CryptoBodyPartMemento *m, KMime::Content *textNode) | 886 | void SignedMessagePart::setVerificationResult(const GpgME::VerificationResult &result, KMime::Content *textNode, const QByteArray &plainText) |
887 | { | 887 | { |
888 | if (const auto vm = dynamic_cast<const VerifyDetachedBodyPartMemento *>(m)) { | 888 | mSignatures = result.signatures(); |
889 | mSignatures = vm->verifyResult().signatures(); | 889 | mVerifiedText = plainText; |
890 | } | 890 | mMetaData.auditLogError = result.error(); |
891 | if (const auto vm = dynamic_cast<const VerifyOpaqueBodyPartMemento *>(m)) { | 891 | if (!mSignatures.empty()) { |
892 | mVerifiedText = vm->plainText(); | 892 | mMetaData.isSigned = true; |
893 | mSignatures = vm->verifyResult().signatures(); | ||
894 | } | ||
895 | if (const auto vm = dynamic_cast<const DecryptVerifyBodyPartMemento *>(m)) { | ||
896 | mVerifiedText = vm->plainText(); | ||
897 | mSignatures = vm->verifyResult().signatures(); | ||
898 | } | ||
899 | mMetaData.auditLogError = m->auditLogError(); | ||
900 | mMetaData.auditLog = m->auditLogAsHtml(); | ||
901 | mMetaData.isSigned = !mSignatures.empty(); | ||
902 | |||
903 | if (mMetaData.isSigned) { | ||
904 | sigStatusToMetaData(); | 893 | sigStatusToMetaData(); |
905 | if (mNode && !textNode) { | 894 | if (mNode && !textNode) { |
906 | mOtp->mNodeHelper->setPartMetaData(mNode, mMetaData); | 895 | mOtp->mNodeHelper->setPartMetaData(mNode, mMetaData); |
@@ -941,11 +930,11 @@ QString SignedMessagePart::htmlContent() const | |||
941 | //-----CryptMessageBlock--------------------- | 930 | //-----CryptMessageBlock--------------------- |
942 | EncryptedMessagePart::EncryptedMessagePart(ObjectTreeParser *otp, | 931 | EncryptedMessagePart::EncryptedMessagePart(ObjectTreeParser *otp, |
943 | const QString &text, | 932 | const QString &text, |
944 | const QGpgME::Protocol *cryptoProto, | 933 | const GpgME::Protocol cryptoProto, |
945 | const QString &fromAddress, | 934 | const QString &fromAddress, |
946 | KMime::Content *node, KMime::Content *encryptedNode) | 935 | KMime::Content *node, KMime::Content *encryptedNode) |
947 | : MessagePart(otp, text, node) | 936 | : MessagePart(otp, text, node) |
948 | , mCryptoProto(cryptoProto) | 937 | , mProtocol(cryptoProto) |
949 | , mFromAddress(fromAddress) | 938 | , mFromAddress(fromAddress) |
950 | , mEncryptedNode(encryptedNode) | 939 | , mEncryptedNode(encryptedNode) |
951 | { | 940 | { |
@@ -1012,32 +1001,21 @@ bool EncryptedMessagePart::okDecryptMIME(KMime::Content &data) | |||
1012 | mMetaData.auditLogError = GpgME::Error(); | 1001 | mMetaData.auditLogError = GpgME::Error(); |
1013 | mMetaData.auditLog.clear(); | 1002 | mMetaData.auditLog.clear(); |
1014 | 1003 | ||
1015 | if (!mCryptoProto) { | ||
1016 | mError = UnknownError; | ||
1017 | mMetaData.errorText = tr("No appropriate crypto plug-in was found."); | ||
1018 | return false; | ||
1019 | } | ||
1020 | |||
1021 | QGpgME::DecryptVerifyJob *job = mCryptoProto->decryptVerifyJob(); | ||
1022 | if (!job) { | ||
1023 | mError = UnknownError; | ||
1024 | mMetaData.errorText = tr("Crypto plug-in \"%1\" cannot decrypt messages.").arg(mCryptoProto->name()); | ||
1025 | return false; | ||
1026 | } | ||
1027 | |||
1028 | const QByteArray ciphertext = data.decodedContent(); | 1004 | const QByteArray ciphertext = data.decodedContent(); |
1029 | auto m = QSharedPointer<DecryptVerifyBodyPartMemento>::create(job, ciphertext); | 1005 | qWarning() << "Protocol: " << mProtocol; |
1030 | m->exec(); | 1006 | auto ctx = gpgContext(mProtocol); |
1031 | 1007 | QGpgME::QByteArrayDataProvider out; | |
1032 | const QByteArray &plainText = m->plainText(); | 1008 | GpgME::Data outdata(&out); |
1033 | const GpgME::DecryptionResult &decryptResult = m->decryptResult(); | 1009 | const std::pair<GpgME::DecryptionResult,GpgME::VerificationResult> res = ctx->decryptAndVerify(fromBA(ciphertext), outdata); |
1034 | const GpgME::VerificationResult &verifyResult = m->verifyResult(); | 1010 | const QByteArray &plainText = out.data(); |
1011 | const GpgME::DecryptionResult &decryptResult = res.first; | ||
1012 | const GpgME::VerificationResult &verifyResult = res.second; | ||
1035 | mMetaData.isSigned = verifyResult.signatures().size() > 0; | 1013 | mMetaData.isSigned = verifyResult.signatures().size() > 0; |
1036 | 1014 | ||
1037 | if (verifyResult.signatures().size() > 0) { | 1015 | if (verifyResult.signatures().size() > 0) { |
1038 | //We simply attach a signed message part to indicate that this content is also signed | 1016 | //We simply attach a signed message part to indicate that this content is also signed |
1039 | auto subPart = SignedMessagePart::Ptr(new SignedMessagePart(mOtp, QString::fromUtf8(plainText), mCryptoProto, mFromAddress, nullptr, nullptr)); | 1017 | auto subPart = SignedMessagePart::Ptr(new SignedMessagePart(mOtp, QString::fromUtf8(plainText), mProtocol, mFromAddress, nullptr, nullptr)); |
1040 | subPart->setVerificationResult(m.data(), nullptr); | 1018 | subPart->setVerificationResult(verifyResult, nullptr, plainText); |
1041 | appendSubPart(subPart); | 1019 | appendSubPart(subPart); |
1042 | } | 1020 | } |
1043 | 1021 | ||
@@ -1075,13 +1053,12 @@ bool EncryptedMessagePart::okDecryptMIME(KMime::Content &data) | |||
1075 | 1053 | ||
1076 | if(noSecKey) { | 1054 | if(noSecKey) { |
1077 | mError = NoKeyError; | 1055 | mError = NoKeyError; |
1078 | mMetaData.errorText = tr("Crypto plug-in \"%1\" could not decrypt the data. ").arg(mCryptoProto->name()) | 1056 | mMetaData.errorText = tr("Could not decrypt the data. ") + tr("No key found for recepients."); |
1079 | + tr("No key found for recepients."); | ||
1080 | } else if (passphraseError) { | 1057 | } else if (passphraseError) { |
1081 | mError = PassphraseError; | 1058 | mError = PassphraseError; |
1082 | } else { | 1059 | } else { |
1083 | mError = UnknownError; | 1060 | mError = UnknownError; |
1084 | mMetaData.errorText = tr("Crypto plug-in \"%1\" could not decrypt the data. ").arg(mCryptoProto->name()) | 1061 | mMetaData.errorText = tr("Could not decrypt the data. ") |
1085 | + tr("Error: %1").arg(mMetaData.errorText); | 1062 | + tr("Error: %1").arg(mMetaData.errorText); |
1086 | } | 1063 | } |
1087 | return false; | 1064 | return false; |