summaryrefslogtreecommitdiffstats
path: root/framework/src/domain/mime/mailcrypto.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/domain/mime/mailcrypto.cpp')
-rw-r--r--framework/src/domain/mime/mailcrypto.cpp99
1 files changed, 57 insertions, 42 deletions
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 @@
44#include <future> 44#include <future>
45#include <utility> 45#include <utility>
46 46
47using namespace MailCrypto;
48
49QDebug operator<< (QDebug d, const MailCrypto::Key &key)
50{
51 d << key.key.primaryFingerprint();
52 return d;
53}
54
55static std::vector<GpgME::Key> toGpgME(const std::vector<Key> keys)
56{
57 std::vector<GpgME::Key> list;
58 std::transform(keys.begin(), keys.end(), std::back_inserter(list), [] (const Key &key) { return key.key; });
59 return list;
60}
61
47// replace simple LFs by CRLFs for all MIME supporting CryptPlugs 62// replace simple LFs by CRLFs for all MIME supporting CryptPlugs
48// according to RfC 2633, 3.1.1 Canonicalization 63// according to RfC 2633, 3.1.1 Canonicalization
49static QByteArray canonicalizeContent(KMime::Content *content) 64static QByteArray canonicalizeContent(KMime::Content *content)
@@ -112,7 +127,7 @@ static QByteArray canonicalizeContent(KMime::Content *content)
112/** 127/**
113 * Get the given `key` in the armor format. 128 * Get the given `key` in the armor format.
114 */ 129 */
115Expected<GpgME::Error, QByteArray> exportPublicKey(const GpgME::Key &key) 130Expected<Error, QByteArray> exportPublicKey(const Key &key)
116{ 131{
117 // Not using the Qt API because it apparently blocks (the `result` signal is never 132 // Not using the Qt API because it apparently blocks (the `result` signal is never
118 // triggered) 133 // triggered)
@@ -122,11 +137,11 @@ Expected<GpgME::Error, QByteArray> exportPublicKey(const GpgME::Key &key)
122 QGpgME::QByteArrayDataProvider dp; 137 QGpgME::QByteArrayDataProvider dp;
123 GpgME::Data data(&dp); 138 GpgME::Data data(&dp);
124 139
125 qDebug() << "Exporting public key:" << key.shortKeyID(); 140 qDebug() << "Exporting public key:" << key.key.shortKeyID();
126 auto error = ctx->exportPublicKeys(key.keyID(), data); 141 auto error = ctx->exportPublicKeys(key.key.keyID(), data);
127 142
128 if (error.code()) { 143 if (error.code()) {
129 return makeUnexpected(error); 144 return makeUnexpected(Error{error});
130 } 145 }
131 146
132 return dp.data(); 147 return dp.data();
@@ -143,14 +158,14 @@ Expected<GpgME::Error, QByteArray> exportPublicKey(const GpgME::Key &key)
143 * 158 *
144 * Used by the `createSignedEmail` and `createEncryptedEmail` functions. 159 * Used by the `createSignedEmail` and `createEncryptedEmail` functions.
145 */ 160 */
146Expected<GpgME::Error, std::unique_ptr<KMime::Content>> 161Expected<Error, std::unique_ptr<KMime::Content>>
147appendPublicKey(std::unique_ptr<KMime::Content> msg, const GpgME::Key &key) 162appendPublicKey(std::unique_ptr<KMime::Content> msg, const Key &key)
148{ 163{
149 const auto publicKeyExportResult = exportPublicKey(key); 164 const auto publicKeyExportResult = exportPublicKey(key);
150 165
151 if (!publicKeyExportResult) { 166 if (!publicKeyExportResult) {
152 // "Could not export public key" 167 // "Could not export public key"
153 return makeUnexpected(publicKeyExportResult.error()); 168 return makeUnexpected(Error{publicKeyExportResult.error()});
154 } 169 }
155 170
156 const auto publicKeyData = publicKeyExportResult.value(); 171 const auto publicKeyData = publicKeyExportResult.value();
@@ -163,7 +178,7 @@ appendPublicKey(std::unique_ptr<KMime::Content> msg, const GpgME::Key &key)
163 { 178 {
164 keyAttachment->contentType()->setMimeType("application/pgp-keys"); 179 keyAttachment->contentType()->setMimeType("application/pgp-keys");
165 keyAttachment->contentDisposition()->setDisposition(KMime::Headers::CDattachment); 180 keyAttachment->contentDisposition()->setDisposition(KMime::Headers::CDattachment);
166 keyAttachment->contentDisposition()->setFilename(QString("0x") + key.shortKeyID() + ".asc"); 181 keyAttachment->contentDisposition()->setFilename(QString("0x") + key.key.shortKeyID() + ".asc");
167 keyAttachment->setBody(publicKeyData); 182 keyAttachment->setBody(publicKeyData);
168 } 183 }
169 184
@@ -177,39 +192,39 @@ appendPublicKey(std::unique_ptr<KMime::Content> msg, const GpgME::Key &key)
177 return result; 192 return result;
178} 193}
179 194
180Expected<GpgME::Error, QByteArray> encrypt(const QByteArray &content, const std::vector<GpgME::Key> &encryptionKeys) 195Expected<Error, QByteArray> encrypt(const QByteArray &content, const std::vector<Key> &encryptionKeys)
181{ 196{
182 QByteArray resultData; 197 QByteArray resultData;
183 198
184 const QGpgME::Protocol *const proto = QGpgME::openpgp(); 199 const QGpgME::Protocol *const proto = QGpgME::openpgp();
185 std::unique_ptr<QGpgME::EncryptJob> job(proto->encryptJob(/* armor = */ true)); 200 std::unique_ptr<QGpgME::EncryptJob> job(proto->encryptJob(/* armor = */ true));
186 const auto result = job->exec(encryptionKeys, content, /* alwaysTrust = */ true, resultData); 201 const auto result = job->exec(toGpgME(encryptionKeys), content, /* alwaysTrust = */ true, resultData);
187 202
188 if (result.error().code()) { 203 if (result.error().code()) {
189 qWarning() << "Encryption failed:" << result.error().asString(); 204 qWarning() << "Encryption failed:" << result.error().asString();
190 return makeUnexpected(result.error()); 205 return makeUnexpected(Error{result.error()});
191 } 206 }
192 207
193 return resultData; 208 return resultData;
194} 209}
195 210
196Expected<GpgME::Error, QByteArray> signAndEncrypt(const QByteArray &content, 211Expected<Error, QByteArray> signAndEncrypt(const QByteArray &content,
197 const std::vector<GpgME::Key> &signingKeys, const std::vector<GpgME::Key> &encryptionKeys) 212 const std::vector<Key> &signingKeys, const std::vector<Key> &encryptionKeys)
198{ 213{
199 QByteArray resultData; 214 QByteArray resultData;
200 215
201 const QGpgME::Protocol *const proto = QGpgME::openpgp(); 216 const QGpgME::Protocol *const proto = QGpgME::openpgp();
202 std::unique_ptr<QGpgME::SignEncryptJob> job(proto->signEncryptJob(/* armor = */ true)); 217 std::unique_ptr<QGpgME::SignEncryptJob> job(proto->signEncryptJob(/* armor = */ true));
203 const auto result = job->exec(signingKeys, encryptionKeys, content, /* alwaysTrust = */ true, resultData); 218 const auto result = job->exec(toGpgME(signingKeys), toGpgME(encryptionKeys), content, /* alwaysTrust = */ true, resultData);
204 219
205 if (result.first.error().code()) { 220 if (result.first.error().code()) {
206 qWarning() << "Signing failed:" << result.first.error().asString(); 221 qWarning() << "Signing failed:" << result.first.error().asString();
207 return makeUnexpected(result.first.error()); 222 return makeUnexpected(Error{result.first.error()});
208 } 223 }
209 224
210 if (result.second.error().code()) { 225 if (result.second.error().code()) {
211 qWarning() << "Encryption failed:" << result.second.error().asString(); 226 qWarning() << "Encryption failed:" << result.second.error().asString();
212 return makeUnexpected(result.second.error()); 227 return makeUnexpected(Error{result.second.error()});
213 } 228 }
214 229
215 return resultData; 230 return resultData;
@@ -276,9 +291,9 @@ std::unique_ptr<KMime::Content> createEncryptedPart(QByteArray encryptedData)
276 * - `application/pgp-keys` (the public key as attachment, which is the first of the 291 * - `application/pgp-keys` (the public key as attachment, which is the first of the
277 * `signingKeys`) 292 * `signingKeys`)
278 */ 293 */
279Expected<GpgME::Error, std::unique_ptr<KMime::Content>> 294Expected<Error, std::unique_ptr<KMime::Content>>
280createEncryptedEmail(KMime::Content *content, const std::vector<GpgME::Key> &encryptionKeys, 295createEncryptedEmail(KMime::Content *content, const std::vector<Key> &encryptionKeys,
281 const GpgME::Key &attachedKey, const std::vector<GpgME::Key> &signingKeys = {}) 296 const Key &attachedKey, const std::vector<Key> &signingKeys = {})
282{ 297{
283 auto contentToEncrypt = canonicalizeContent(content); 298 auto contentToEncrypt = canonicalizeContent(content);
284 299
@@ -287,7 +302,7 @@ createEncryptedEmail(KMime::Content *content, const std::vector<GpgME::Key> &enc
287 signAndEncrypt(contentToEncrypt, signingKeys, encryptionKeys); 302 signAndEncrypt(contentToEncrypt, signingKeys, encryptionKeys);
288 303
289 if (!encryptionResult) { 304 if (!encryptionResult) {
290 return makeUnexpected(encryptionResult.error()); 305 return makeUnexpected(Error{encryptionResult.error()});
291 } 306 }
292 307
293 auto encryptedPart = createEncryptedPart(encryptionResult.value()); 308 auto encryptedPart = createEncryptedPart(encryptionResult.value());
@@ -305,18 +320,18 @@ createEncryptedEmail(KMime::Content *content, const std::vector<GpgME::Key> &enc
305 * Sign the given content and returns the signing data and the algorithm used 320 * Sign the given content and returns the signing data and the algorithm used
306 * for integrity check in the "pgp-<algorithm>" format. 321 * for integrity check in the "pgp-<algorithm>" format.
307 */ 322 */
308Expected<GpgME::Error, std::pair<QByteArray, QString>> 323Expected<Error, std::pair<QByteArray, QString>>
309sign(const QByteArray &content, const std::vector<GpgME::Key> &signingKeys) 324sign(const QByteArray &content, const std::vector<Key> &signingKeys)
310{ 325{
311 QByteArray resultData; 326 QByteArray resultData;
312 327
313 const QGpgME::Protocol *const proto = QGpgME::openpgp(); 328 const QGpgME::Protocol *const proto = QGpgME::openpgp();
314 std::unique_ptr<QGpgME::SignJob> job(proto->signJob(/* armor = */ true)); 329 std::unique_ptr<QGpgME::SignJob> job(proto->signJob(/* armor = */ true));
315 const auto result = job->exec(signingKeys, content, GpgME::Detached, resultData); 330 const auto result = job->exec(toGpgME(signingKeys), content, GpgME::Detached, resultData);
316 331
317 if (result.error().code()) { 332 if (result.error().code()) {
318 qWarning() << "Signing failed:" << result.error().asString(); 333 qWarning() << "Signing failed:" << result.error().asString();
319 return makeUnexpected(result.error()); 334 return makeUnexpected(Error{result.error()});
320 } 335 }
321 336
322 auto algo = result.createdSignature(0).hashAlgorithmAsString(); 337 auto algo = result.createdSignature(0).hashAlgorithmAsString();
@@ -380,9 +395,9 @@ std::unique_ptr<KMime::Content> createSignedPart(
380 * - `application/pgp-keys` (the public key as attachment, which is the first of the 395 * - `application/pgp-keys` (the public key as attachment, which is the first of the
381 * `signingKeys`) 396 * `signingKeys`)
382 */ 397 */
383Expected<GpgME::Error, std::unique_ptr<KMime::Content>> 398Expected<Error, std::unique_ptr<KMime::Content>>
384createSignedEmail(std::unique_ptr<KMime::Content> content, 399createSignedEmail(std::unique_ptr<KMime::Content> content,
385 const std::vector<GpgME::Key> &signingKeys, const GpgME::Key &attachedKey) 400 const std::vector<Key> &signingKeys, const Key &attachedKey)
386{ 401{
387 Q_ASSERT(!signingKeys.empty()); 402 Q_ASSERT(!signingKeys.empty());
388 403
@@ -391,7 +406,7 @@ createSignedEmail(std::unique_ptr<KMime::Content> content,
391 auto signingResult = sign(contentToSign, signingKeys); 406 auto signingResult = sign(contentToSign, signingKeys);
392 407
393 if (!signingResult) { 408 if (!signingResult) {
394 return makeUnexpected(signingResult.error()); 409 return makeUnexpected(Error{signingResult.error()});
395 } 410 }
396 411
397 QByteArray signingData; 412 QByteArray signingData;
@@ -409,9 +424,9 @@ createSignedEmail(std::unique_ptr<KMime::Content> content,
409 return publicKeyAppendResult; 424 return publicKeyAppendResult;
410} 425}
411 426
412Expected<GpgME::Error, std::unique_ptr<KMime::Content>> 427Expected<Error, std::unique_ptr<KMime::Content>>
413MailCrypto::processCrypto(std::unique_ptr<KMime::Content> content, const std::vector<GpgME::Key> &signingKeys, 428MailCrypto::processCrypto(std::unique_ptr<KMime::Content> content, const std::vector<Key> &signingKeys,
414 const std::vector<GpgME::Key> &encryptionKeys, const GpgME::Key &attachedKey) 429 const std::vector<Key> &encryptionKeys, const Key &attachedKey)
415{ 430{
416 if (!encryptionKeys.empty()) { 431 if (!encryptionKeys.empty()) {
417 return createEncryptedEmail(content.release(), encryptionKeys, attachedKey, signingKeys); 432 return createEncryptedEmail(content.release(), encryptionKeys, attachedKey, signingKeys);
@@ -423,12 +438,12 @@ MailCrypto::processCrypto(std::unique_ptr<KMime::Content> content, const std::ve
423 } 438 }
424} 439}
425 440
426void MailCrypto::importKeys(const std::vector<GpgME::Key> &keys) 441void MailCrypto::importKeys(const std::vector<Key> &keys)
427{ 442{
428 const QGpgME::Protocol *const backend = QGpgME::openpgp(); 443 const QGpgME::Protocol *const backend = QGpgME::openpgp();
429 Q_ASSERT(backend); 444 Q_ASSERT(backend);
430 auto *job = backend->importFromKeyserverJob(); 445 auto *job = backend->importFromKeyserverJob();
431 job->exec(keys); 446 job->exec(toGpgME(keys));
432} 447}
433 448
434MailCrypto::ImportResult MailCrypto::importKey(const QByteArray &pkey) 449MailCrypto::ImportResult MailCrypto::importKey(const QByteArray &pkey)
@@ -439,7 +454,7 @@ MailCrypto::ImportResult MailCrypto::importKey(const QByteArray &pkey)
439 return {result.numConsidered(), result.numImported(), result.numUnchanged()}; 454 return {result.numConsidered(), result.numImported(), result.numUnchanged()};
440} 455}
441 456
442static GpgME::KeyListResult listKeys(const QStringList &patterns, bool secretOnly, int keyListMode, std::vector<GpgME::Key> &keys) 457static GpgME::KeyListResult listKeys(const QStringList &patterns, bool secretOnly, int keyListMode, std::vector<Key> &keys)
443{ 458{
444 QByteArrayList list; 459 QByteArrayList list;
445 std::transform(patterns.constBegin(), patterns.constEnd(), std::back_inserter(list), [] (const QString &s) { return s.toUtf8(); }); 460 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
456 471
457 GpgME::Error err; 472 GpgME::Error err;
458 do { 473 do {
459 keys.push_back( ctx->nextKey(err)); 474 keys.push_back( Key{ctx->nextKey(err)});
460 } while ( !err ); 475 } while ( !err );
461 476
462 keys.pop_back(); 477 keys.pop_back();
@@ -466,21 +481,21 @@ static GpgME::KeyListResult listKeys(const QStringList &patterns, bool secretOnl
466 return result; 481 return result;
467} 482}
468 483
469std::vector<GpgME::Key> MailCrypto::findKeys(const QStringList &filter, bool findPrivate, bool remote) 484std::vector<Key> MailCrypto::findKeys(const QStringList &filter, bool findPrivate, bool remote)
470{ 485{
471 std::vector<GpgME::Key> keys; 486 std::vector<Key> keys;
472 GpgME::KeyListResult res = listKeys(filter, findPrivate, remote ? GpgME::Extern : GpgME::Local, keys); 487 GpgME::KeyListResult res = listKeys(filter, findPrivate, remote ? GpgME::Extern : GpgME::Local, keys);
473 if (res.error()) { 488 if (res.error()) {
474 qWarning() << "Failed to lookup keys: " << res.error().asString(); 489 qWarning() << "Failed to lookup keys: " << res.error().asString();
475 return keys; 490 return {};
476 } 491 }
477 qWarning() << "got keys:" << keys.size(); 492 qWarning() << "got keys:" << keys.size();
478 493
479 for (std::vector< GpgME::Key >::iterator i = keys.begin(); i != keys.end(); ++i) { 494 for (auto i = keys.begin(); i != keys.end(); ++i) {
480 qWarning() << "key isnull:" << i->isNull() << "isexpired:" << i->isExpired(); 495 qWarning() << "key isnull:" << i->key.isNull() << "isexpired:" << i->key.isExpired();
481 qWarning() << "key numuserIds:" << i->numUserIDs(); 496 qWarning() << "key numuserIds:" << i->key.numUserIDs();
482 for (uint k = 0; k < i->numUserIDs(); ++k) { 497 for (uint k = 0; k < i->key.numUserIDs(); ++k) {
483 qWarning() << "userIDs:" << i->userID(k).email(); 498 qWarning() << "userIDs:" << i->key.userID(k).email();
484 } 499 }
485 } 500 }
486 501