diff options
Diffstat (limited to 'framework/src/domain/mime/mailcrypto.cpp')
-rw-r--r-- | framework/src/domain/mime/mailcrypto.cpp | 99 |
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 | ||
47 | using namespace MailCrypto; | ||
48 | |||
49 | QDebug operator<< (QDebug d, const MailCrypto::Key &key) | ||
50 | { | ||
51 | d << key.key.primaryFingerprint(); | ||
52 | return d; | ||
53 | } | ||
54 | |||
55 | static 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 |
49 | static QByteArray canonicalizeContent(KMime::Content *content) | 64 | static 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 | */ |
115 | Expected<GpgME::Error, QByteArray> exportPublicKey(const GpgME::Key &key) | 130 | Expected<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 | */ |
146 | Expected<GpgME::Error, std::unique_ptr<KMime::Content>> | 161 | Expected<Error, std::unique_ptr<KMime::Content>> |
147 | appendPublicKey(std::unique_ptr<KMime::Content> msg, const GpgME::Key &key) | 162 | appendPublicKey(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 | ||
180 | Expected<GpgME::Error, QByteArray> encrypt(const QByteArray &content, const std::vector<GpgME::Key> &encryptionKeys) | 195 | Expected<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 | ||
196 | Expected<GpgME::Error, QByteArray> signAndEncrypt(const QByteArray &content, | 211 | Expected<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 | */ |
279 | Expected<GpgME::Error, std::unique_ptr<KMime::Content>> | 294 | Expected<Error, std::unique_ptr<KMime::Content>> |
280 | createEncryptedEmail(KMime::Content *content, const std::vector<GpgME::Key> &encryptionKeys, | 295 | createEncryptedEmail(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 | */ |
308 | Expected<GpgME::Error, std::pair<QByteArray, QString>> | 323 | Expected<Error, std::pair<QByteArray, QString>> |
309 | sign(const QByteArray &content, const std::vector<GpgME::Key> &signingKeys) | 324 | sign(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 | */ |
383 | Expected<GpgME::Error, std::unique_ptr<KMime::Content>> | 398 | Expected<Error, std::unique_ptr<KMime::Content>> |
384 | createSignedEmail(std::unique_ptr<KMime::Content> content, | 399 | createSignedEmail(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 | ||
412 | Expected<GpgME::Error, std::unique_ptr<KMime::Content>> | 427 | Expected<Error, std::unique_ptr<KMime::Content>> |
413 | MailCrypto::processCrypto(std::unique_ptr<KMime::Content> content, const std::vector<GpgME::Key> &signingKeys, | 428 | MailCrypto::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 | ||
426 | void MailCrypto::importKeys(const std::vector<GpgME::Key> &keys) | 441 | void 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 | ||
434 | MailCrypto::ImportResult MailCrypto::importKey(const QByteArray &pkey) | 449 | MailCrypto::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 | ||
442 | static GpgME::KeyListResult listKeys(const QStringList &patterns, bool secretOnly, int keyListMode, std::vector<GpgME::Key> &keys) | 457 | static 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 | ||
469 | std::vector<GpgME::Key> MailCrypto::findKeys(const QStringList &filter, bool findPrivate, bool remote) | 484 | std::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 | ||