Return-Path: X-Original-To: notmuch@notmuchmail.org Delivered-To: notmuch@notmuchmail.org Received: from localhost (localhost [127.0.0.1]) by arlo.cworth.org (Postfix) with ESMTP id 1B5C16DE0FF1 for ; Wed, 9 Dec 2015 19:40:09 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at cworth.org X-Spam-Flag: NO X-Spam-Score: -0.035 X-Spam-Level: X-Spam-Status: No, score=-0.035 tagged_above=-999 required=5 tests=[AWL=-0.035] autolearn=disabled Received: from arlo.cworth.org ([127.0.0.1]) by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 5UbXq0YuG3Ap for ; Wed, 9 Dec 2015 19:40:05 -0800 (PST) Received: from che.mayfirst.org (che.mayfirst.org [209.234.253.108]) by arlo.cworth.org (Postfix) with ESMTP id D46A36DE005F for ; Wed, 9 Dec 2015 19:40:04 -0800 (PST) Received: from fifthhorseman.net (unknown [38.109.115.130]) by che.mayfirst.org (Postfix) with ESMTPSA id 09188F985 for ; Wed, 9 Dec 2015 22:40:03 -0500 (EST) Received: by fifthhorseman.net (Postfix, from userid 1000) id AC13120CF1; Wed, 9 Dec 2015 22:40:03 -0500 (EST) From: Daniel Kahn Gillmor To: Notmuch Mail Subject: [PATCH 3/9] index encrypted parts when the message is flagged appropriately Date: Wed, 9 Dec 2015 22:39:40 -0500 Message-Id: <1449718786-28000-4-git-send-email-dkg@fifthhorseman.net> X-Mailer: git-send-email 2.6.2 In-Reply-To: <1449718786-28000-1-git-send-email-dkg@fifthhorseman.net> References: <1449718786-28000-1-git-send-email-dkg@fifthhorseman.net> X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 10 Dec 2015 03:40:09 -0000 We add a new message flag that indicates desire for indexing the cleartext of a given message. If that flag is set while indexing, we'll try to descend into it. If we can decrypt, we tag the message with index-decrypted. If we can't decrypt (or recognize the encrypted type of mail), we tag with decryption-failed. Note that a single message may be tagged with "encrypted" and "index-decrypted" and "decryption-failed". For example, consider a message that includes multiple layers of encryption. It is automatically tagged with "encrypted". If we decrypt the outer layer ("index-decrypted"), but fail on the inner layer ("decryption-failed"). --- lib/index.cc | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- lib/notmuch.h | 5 +++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/lib/index.cc b/lib/index.cc index 2fa6616..bd028cb 100644 --- a/lib/index.cc +++ b/lib/index.cc @@ -300,6 +300,10 @@ _index_address_list (notmuch_message_t *message, } } +static void +_index_encrypted_mime_part (notmuch_message_t *message, GMimeContentType *content_type, + GMimeMultipartEncrypted *part); + /* Callback to generate terms for each mime part of a message. */ static void _index_mime_part (notmuch_message_t *message, @@ -346,7 +350,10 @@ _index_mime_part (notmuch_message_t *message, _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"); + if (notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_INDEX_DECRYPTED)) { + _index_encrypted_mime_part(message, content_type, GMIME_MULTIPART_ENCRYPTED (part)); + } } else { for (i = 0; i < g_mime_multipart_get_count (multipart); i++) { _index_mime_part (message, @@ -431,6 +438,49 @@ _index_mime_part (notmuch_message_t *message, } } +/* descend (if possible) into the cleartext part of an encrypted MIME + * part while indexing. */ +static void +_index_encrypted_mime_part (notmuch_message_t *message, + GMimeContentType *content_type, + GMimeMultipartEncrypted *encrypted_data) +{ + notmuch_private_status_t status; + GMimeCryptoContext* crypto_ctx = NULL; + const char *protocol = g_mime_content_type_get_parameter (content_type, "protocol"); + GError *err = NULL; + notmuch_database_t * notmuch = _notmuch_message_database (message); + GMimeObject *clear = NULL; + + status = _notmuch_database_get_crypto_for_protocol (notmuch, protocol, + &crypto_ctx); + if (status) { + _notmuch_database_log (notmuch, "Warning: setup failed for decrypting " + "during indexing. (%d)\n", status); + _notmuch_message_add_term (message, "tag", "index-decryption-failed"); + return; + } + + /* 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 */ + _notmuch_message_add_term (message, "tag", "index-decryption-failed"); + return; + } + _index_mime_part (message, clear); + g_object_unref (clear); + + _notmuch_message_add_term (message, "tag", "index-decrypted"); +} + notmuch_status_t _notmuch_message_index_file (notmuch_message_t *message, notmuch_message_file_t *message_file) diff --git a/lib/notmuch.h b/lib/notmuch.h index 310a8b8..e7085b7 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -1357,6 +1357,11 @@ typedef enum _notmuch_message_flag { * thread ID. */ NOTMUCH_MESSAGE_FLAG_GHOST, + + /* Some part(s) of this message is encrypted, but the message is + * indexed in the clear. + */ + NOTMUCH_MESSAGE_FLAG_INDEX_DECRYPTED } notmuch_message_flag_t; /** -- 2.6.2