If we see index options that ask us to decrypt when indexing a message, and we encounter an encrypted part, we'll try to descend into it. If we can decrypt, we add the property index-decryption=success. If we can't decrypt (or recognize the encrypted type of mail), we add the property index-decryption=failure. Note that a single message may have both values of the "index-decryption" property: "success" and "failure". For example, consider a message that includes multiple layers of encryption. If we manage to decrypt the outer layer ("index-decryption=success"), but fail on the inner layer ("index-decryption=failure"). Before re-indexing, we wipe this automatically-added property, so that it will subsequently correspond to the actual semantics of the stored index. --- lib/add-message.cc | 2 +- lib/index.cc | 86 +++++++++++++++++++++++++++++++++++++++++++++++++-- lib/message.cc | 14 +++++++-- lib/notmuch-private.h | 1 + 4 files changed, 97 insertions(+), 6 deletions(-) diff --git a/lib/add-message.cc b/lib/add-message.cc index 1fd91c14..66eb0a1f 100644 --- a/lib/add-message.cc +++ b/lib/add-message.cc @@ -544,7 +544,7 @@ notmuch_database_index_file (notmuch_database_t *notmuch, if (!indexopts) indexopts = def_indexopts = notmuch_database_get_default_indexopts (notmuch); - ret = _notmuch_message_index_file (message, message_file); + ret = _notmuch_message_index_file (message, indexopts, message_file); if (ret) goto DONE; diff --git a/lib/index.cc b/lib/index.cc index 3ed3b2c6..2efac307 100644 --- a/lib/index.cc +++ b/lib/index.cc @@ -351,9 +351,17 @@ _index_address_list (notmuch_message_t *message, } } +static void +_index_encrypted_mime_part (notmuch_message_t *message, notmuch_indexopts_t *indexopts, +#if (GMIME_MAJOR_VERSION < 3) + GMimeContentType *content_type, +#endif + GMimeMultipartEncrypted *part); + /* Callback to generate terms for each mime part of a message. */ static void _index_mime_part (notmuch_message_t *message, + notmuch_indexopts_t *indexopts, GMimeObject *part) { GMimeStream *stream, *filter; @@ -394,17 +402,23 @@ _index_mime_part (notmuch_message_t *message, application/pkcs7-signature, which is all gmime can handle anyway. */ _index_mime_part (message, + indexopts, g_mime_multipart_get_part (multipart, 0)); if (g_mime_multipart_get_count (multipart) > 2) _notmuch_database_log (_notmuch_message_database (message), "Warning: Unexpected extra parts of multipart/signed. Indexing anyway.\n"); } else if (GMIME_IS_MULTIPART_ENCRYPTED (multipart)) { - /* Don't index encrypted parts */ _notmuch_message_add_term (message, "tag", "encrypted"); + _index_encrypted_mime_part(message, indexopts, +#if (GMIME_MAJOR_VERSION < 3) + content_type, +#endif + GMIME_MULTIPART_ENCRYPTED (part)); } else { for (i = 0; i < g_mime_multipart_get_count (multipart); i++) { _index_mime_part (message, + indexopts, g_mime_multipart_get_part (multipart, i)); } } @@ -416,7 +430,7 @@ _index_mime_part (notmuch_message_t *message, mime_message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (part)); - _index_mime_part (message, g_mime_message_get_mime_part (mime_message)); + _index_mime_part (message, indexopts, g_mime_message_get_mime_part (mime_message)); return; } @@ -486,8 +500,74 @@ _index_mime_part (notmuch_message_t *message, } } +/* descend (if desired) into the cleartext part of an encrypted MIME + * part while indexing. */ +static void +_index_encrypted_mime_part (notmuch_message_t *message, + notmuch_indexopts_t *indexopts, +#if (GMIME_MAJOR_VERSION < 3) + GMimeContentType *content_type, +#endif + GMimeMultipartEncrypted *encrypted_data) +{ + notmuch_status_t status; +#if (GMIME_MAJOR_VERSION < 3) + GMimeCryptoContext* crypto_ctx = NULL; + const char *protocol = NULL; +#endif + GError *err = NULL; + notmuch_database_t * notmuch = NULL; + GMimeObject *clear = NULL; + + if (!indexopts || !notmuch_indexopts_get_try_decrypt (indexopts)) + return; + + notmuch = _notmuch_message_database (message); + +#if (GMIME_MAJOR_VERSION < 3) + protocol = g_mime_content_type_get_parameter (content_type, "protocol"); + status = _notmuch_crypto_get_gmime_ctx_for_protocol (&(indexopts->crypto), + protocol, &crypto_ctx); + if (status) { + _notmuch_database_log (notmuch, "Warning: setup failed for decrypting " + "during indexing. (%d)\n", status); + status = notmuch_message_add_property (message, "index-decryption", "failure"); + if (status) + _notmuch_database_log (notmuch, "failed to add index-decryption " + "property (%d)\n", status); + return; + } +#endif + /* we don't need the GMimeDecryptResult, because we're not looking + * at validating signatures, and we don't care about indexing who + * the message was ostensibly encrypted to. + */ + clear = g_mime_multipart_encrypted_decrypt(encrypted_data, crypto_ctx, + NULL, &err); + if (err) { + _notmuch_database_log (notmuch, "Failed to decrypt during indexing. (%d:%d) [%s]\n", + err->domain, err->code, err->message); + g_error_free(err); + /* Indicate that we failed to decrypt during indexing */ + status = notmuch_message_add_property (message, "index-decryption", "failure"); + if (status) + _notmuch_database_log (notmuch, "failed to add index-decryption " + "property (%d)\n", status); + return; + } + _index_mime_part (message, indexopts, clear); + g_object_unref (clear); + + status = notmuch_message_add_property (message, "index-decryption", "success"); + if (status) + _notmuch_database_log (notmuch, "failed to add index-decryption " + "property (%d)\n", status); + +} + notmuch_status_t _notmuch_message_index_file (notmuch_message_t *message, + notmuch_indexopts_t *indexopts, notmuch_message_file_t *message_file) { GMimeMessage *mime_message; @@ -515,7 +595,7 @@ _notmuch_message_index_file (notmuch_message_t *message, subject = g_mime_message_get_subject (mime_message); _notmuch_message_gen_terms (message, "subject", subject); - _index_mime_part (message, g_mime_message_get_mime_part (mime_message)); + _index_mime_part (message, indexopts, g_mime_message_get_mime_part (mime_message)); return NOTMUCH_STATUS_SUCCESS; } diff --git a/lib/message.cc b/lib/message.cc index 0e3b5a4f..2ffa25a3 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -1961,7 +1961,7 @@ _notmuch_message_frozen (notmuch_message_t *message) notmuch_status_t notmuch_message_reindex (notmuch_message_t *message, - notmuch_indexopts_t unused (*indexopts)) + notmuch_indexopts_t *indexopts) { notmuch_database_t *notmuch = NULL; notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS; @@ -1969,6 +1969,7 @@ notmuch_message_reindex (notmuch_message_t *message, notmuch_filenames_t *orig_filenames = NULL; const char *orig_thread_id = NULL; notmuch_message_file_t *message_file = NULL; + const char *autoproperties[] = { "index-decryption" }; int found = 0; @@ -1999,6 +2000,15 @@ notmuch_message_reindex (notmuch_message_t *message, goto DONE; } + /* all automatically-added properties should be removed before re-indexing */ + for (size_t i = 0; i < ARRAY_SIZE (autoproperties); i++) { + ret = notmuch_message_remove_all_properties (message, autoproperties[i]); + if (ret) { + INTERNAL_ERROR ("failed to remove automatically-added property '%s'", autoproperties[i]); + goto DONE; + } + } + /* re-add the filenames with the associated indexopts */ for (; notmuch_filenames_valid (orig_filenames); notmuch_filenames_move_to_next (orig_filenames)) { @@ -2038,7 +2048,7 @@ notmuch_message_reindex (notmuch_message_t *message, if (found == 0) _notmuch_message_set_header_values (message, date, from, subject); - ret = _notmuch_message_index_file (message, message_file); + ret = _notmuch_message_index_file (message, indexopts, message_file); if (ret == NOTMUCH_STATUS_FILE_ERROR) continue; diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 3168cf3c..362106c8 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -447,6 +447,7 @@ _notmuch_database_link_message_to_parents (notmuch_database_t *notmuch, notmuch_status_t _notmuch_message_index_file (notmuch_message_t *message, + notmuch_indexopts_t *indexopts, notmuch_message_file_t *message_file); /* messages.c */ -- 2.14.1 _______________________________________________ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch