From bd6e2b880265d01fbb8f4cbeb909ba9dda4f18d2 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 8 Mar 2018 11:00:33 +0100 Subject: Switching to unique_ptr everywhere (+ fixing micalg) --- framework/src/domain/mime/mailcrypto.cpp | 95 +++++++++++++++-------------- framework/src/domain/mime/mailcrypto.h | 10 ++- framework/src/domain/mime/mailtemplates.cpp | 7 +-- 3 files changed, 61 insertions(+), 51 deletions(-) diff --git a/framework/src/domain/mime/mailcrypto.cpp b/framework/src/domain/mime/mailcrypto.cpp index 83ce293a..4e20c84b 100644 --- a/framework/src/domain/mime/mailcrypto.cpp +++ b/framework/src/domain/mime/mailcrypto.cpp @@ -142,18 +142,19 @@ Expected exportPublicKey(const GpgME::Key &key) * * Used by the `createSignedEmail` and `createEncryptedEmail` functions. */ -Expected appendPublicKey(KMime::Content *msg, const GpgME::Key &key) +Expected> +appendPublicKey(std::unique_ptr msg, const GpgME::Key &key) { const auto publicKeyExportResult = exportPublicKey(key); - if(!publicKeyExportResult) { + if (!publicKeyExportResult) { // "Could not export public key" return makeUnexpected(publicKeyExportResult.error()); } const auto publicKeyData = publicKeyExportResult.value(); - auto result = new KMime::Content; + auto result = std::unique_ptr(new KMime::Content); result->contentType()->setMimeType("multipart/mixed"); result->contentType()->setBoundary(KMime::multiPartBoundary()); @@ -166,13 +167,11 @@ Expected appendPublicKey(KMime::Content *msg, co } msg->assemble(); - qWarning() << "Msg:" << msg->encodedContent().constData(); - result->addContent(msg); + result->addContent(msg.release()); result->addContent(keyAttachment); result->assemble(); - qDebug() << "Final message:\n" << result->encodedContent().constData(); return result; } @@ -193,8 +192,8 @@ Expected encrypt(const QByteArray &content, const std: 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; @@ -216,7 +215,7 @@ Expected signAndEncrypt(const QByteArray &content, con } /** - * Create a message like this (according to RFC 3156 Section 4): + * Create a message part like this (according to RFC 3156 Section 4): * * - multipart/encrypted * - application/pgp-encrypted (version information) @@ -227,9 +226,9 @@ Expected signAndEncrypt(const QByteArray &content, con * * The encrypted data can be generated by the `encrypt` or `signAndEncrypt` functions. */ -KMime::Content *createEncryptedPart(QByteArray encryptedData) +std::unique_ptr createEncryptedPart(QByteArray encryptedData) { - KMime::Content *result = new KMime::Content; + auto result = std::unique_ptr(new KMime::Content); result->contentType()->setMimeType("multipart/encrypted"); result->contentType()->setBoundary(KMime::multiPartBoundary()); @@ -276,7 +275,7 @@ KMime::Content *createEncryptedPart(QByteArray encryptedData) * - `application/pgp-keys` (the public key as attachment, which is the first of the * `signingKeys`) */ -Expected +Expected> createEncryptedEmail(KMime::Content *content, const std::vector &encryptionKeys, const GpgME::Key &attachedKey, const std::vector &signingKeys = {}) { @@ -290,21 +289,23 @@ createEncryptedEmail(KMime::Content *content, const std::vector &enc return makeUnexpected(encryptionResult.error()); } - auto encryptedData = encryptionResult.value(); + auto encryptedPart = createEncryptedPart(encryptionResult.value()); - KMime::Content *encryptedPart = createEncryptedPart(encryptedData); + auto publicKeyAppendResult = appendPublicKey(std::move(encryptedPart), attachedKey); - auto publicKeyAppendResult = appendPublicKey(encryptedPart, attachedKey); - - // TODO: this is ugly - if (!publicKeyAppendResult) { - delete encryptedPart; + if(publicKeyAppendResult) { + publicKeyAppendResult.value()->assemble(); } return publicKeyAppendResult; } -Expected sign(const QByteArray &content, const std::vector &signingKeys) +/** + * 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) { QByteArray resultData; @@ -317,11 +318,17 @@ Expected sign(const QByteArray &content, const std::ve return makeUnexpected(result.error()); } - return resultData; + auto algo = result.createdSignature(0).hashAlgorithmAsString(); + // RFC 3156 Section 5: + // Hash-symbols are constructed [...] by converting the text name to lower + // case and prefixing it with the four characters "pgp-". + auto micAlg = (QString("pgp-") + algo).toLower(); + + return std::pair{resultData, micAlg}; } /** - * Create a message like this (according to RFC 3156 Section 5): + * Create a message part like this (according to RFC 3156 Section 5): * * + `multipart/signed` * - whatever the given original `message` is (should be canonicalized) @@ -332,16 +339,17 @@ Expected sign(const QByteArray &content, const std::ve * * The signature can be generated by the `sign` function. */ -KMime::Content *createSignedPart(KMime::Content *message, const QByteArray &signature, const QString &micAlg) +std::unique_ptr createSignedPart( + std::unique_ptr message, const QByteArray &signature, const QString &micAlg) { - KMime::Content *result = new KMime::Content; + auto result = std::unique_ptr(new KMime::Content); result->contentType()->setMimeType("multipart/signed"); result->contentType()->setBoundary(KMime::multiPartBoundary()); result->contentType()->setParameter("micalg", micAlg); result->contentType()->setParameter("protocol", "application/pgp-signature"); - result->addContent(message); + result->addContent(message.release()); KMime::Content *signedPartPart = new KMime::Content; { @@ -371,12 +379,13 @@ KMime::Content *createSignedPart(KMime::Content *message, const QByteArray &sign * - `application/pgp-keys` (the public key as attachment, which is the first of the * `signingKeys`) */ -Expected createSignedEmail(KMime::Content *content, +Expected> +createSignedEmail(std::unique_ptr content, const std::vector &signingKeys, const GpgME::Key &attachedKey) { Q_ASSERT(!signingKeys.empty()); - auto contentToSign = canonicalizeContent(content); + auto contentToSign = canonicalizeContent(content.get()); auto signingResult = sign(contentToSign, signingKeys); @@ -384,33 +393,29 @@ Expected createSignedEmail(KMime::Content *conte return makeUnexpected(signingResult.error()); } - auto signedData = signingResult.value(); + QByteArray signingData; + QString micAlg; + std::tie(signingData, micAlg) = signingResult.value(); - KMime::Content *signedPart = createSignedPart(content, signedData, "TODO: pgp-something"); + auto signedPart = createSignedPart(std::move(content), signingData, micAlg); - auto publicKeyAppendResult = appendPublicKey(signedPart, attachedKey); + auto publicKeyAppendResult = appendPublicKey(std::move(signedPart), attachedKey); - // TODO: this is ugly (maybe use a std::unique_ptr for signedPart) - if (!publicKeyAppendResult) { - delete signedPart; + if (publicKeyAppendResult) { + publicKeyAppendResult.value()->assemble(); } return publicKeyAppendResult; } -KMime::Content *MailCrypto::processCrypto(KMime::Content *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 GpgME::Key &attachedKey) { - - qDebug() << "Attaching key:" << attachedKey.shortKeyID() << "from processCrypto"; - - if(!encryptionKeys.empty()) { - // TODO - return createEncryptedEmail(content, encryptionKeys, attachedKey, signingKeys).value(); - } else if(!signingKeys.empty()) { - // TODO - return createSignedEmail(content, signingKeys, signingKeys[0]).value(); + if (!encryptionKeys.empty()) { + return createEncryptedEmail(content.release(), encryptionKeys, attachedKey, signingKeys); + } else if (!signingKeys.empty()) { + return createSignedEmail(std::move(content), signingKeys, signingKeys[0]); } else { qWarning() << "Processing cryptography, but neither signing nor encrypting"; return content; diff --git a/framework/src/domain/mime/mailcrypto.h b/framework/src/domain/mime/mailcrypto.h index 89343fc9..832f68ec 100644 --- a/framework/src/domain/mime/mailcrypto.h +++ b/framework/src/domain/mime/mailcrypto.h @@ -19,14 +19,20 @@ #pragma once +#include "framework/src/errors.h" + #include +#include + #include + #include -#include +#include namespace MailCrypto { -KMime::Content *processCrypto(KMime::Content *content, const std::vector &signingKeys, +Expected> +processCrypto(std::unique_ptr content, const std::vector &signingKeys, const std::vector &encryptionKeys, const GpgME::Key &attachedKey); std::vector findKeys(const QStringList &filter, bool findPrivate = false, bool remote = false); diff --git a/framework/src/domain/mime/mailtemplates.cpp b/framework/src/domain/mime/mailtemplates.cpp index 09932e86..997eb3ae 100644 --- a/framework/src/domain/mime/mailtemplates.cpp +++ b/framework/src/domain/mime/mailtemplates.cpp @@ -1093,13 +1093,12 @@ KMime::Message::Ptr MailTemplates::createMessage(KMime::Message::Ptr existingMes QByteArray bodyData; if (!signingKeys.empty() || !encryptionKeys.empty()) { - auto result = MailCrypto::processCrypto( - bodyPart.get(), signingKeys, encryptionKeys, attachedKey); + auto result = MailCrypto::processCrypto(std::move(bodyPart), signingKeys, encryptionKeys, attachedKey); if (!result) { - qWarning() << "Signing failed"; + qWarning() << "Crypto failed"; return {}; } - bodyData = result->encodedContent(); + bodyData = result.value()->encodedContent(); } else { if (!bodyPart->contentType(false)) { bodyPart->contentType(true)->setMimeType("text/plain"); -- cgit v1.2.3