--- /dev/null
+Return-Path: <dkg@fifthhorseman.net>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by arlo.cworth.org (Postfix) with ESMTP id 2E2736DE091F\r
+ for <notmuch@notmuchmail.org>; Fri, 8 Jul 2016 03:15:53 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at cworth.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0.108\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0.108 tagged_above=-999 required=5 tests=[AWL=0.108]\r
+ autolearn=disabled\r
+Received: from arlo.cworth.org ([127.0.0.1])\r
+ by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id lcP0jSlf_7qU for <notmuch@notmuchmail.org>;\r
+ Fri, 8 Jul 2016 03:15:45 -0700 (PDT)\r
+Received: from che.mayfirst.org (che.mayfirst.org [162.247.75.118])\r
+ by arlo.cworth.org (Postfix) with ESMTP id 8C5226DE0931\r
+ for <notmuch@notmuchmail.org>; Fri, 8 Jul 2016 03:13:25 -0700 (PDT)\r
+Received: from fifthhorseman.net (unknown [88.128.80.54])\r
+ by che.mayfirst.org (Postfix) with ESMTPSA id 49617F993\r
+ for <notmuch@notmuchmail.org>; Fri, 8 Jul 2016 06:13:24 -0400 (EDT)\r
+Received: by fifthhorseman.net (Postfix, from userid 1000)\r
+ id AF49D213E0; Fri, 8 Jul 2016 11:27:34 +0200 (CEST)\r
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>\r
+To: Notmuch Mail <notmuch@notmuchmail.org>\r
+Subject: [PATCH v4 09/16] index encrypted parts when asked.\r
+Date: Fri, 8 Jul 2016 11:27:20 +0200\r
+Message-Id: <1467970047-8013-10-git-send-email-dkg@fifthhorseman.net>\r
+X-Mailer: git-send-email 2.8.1\r
+In-Reply-To: <1467970047-8013-1-git-send-email-dkg@fifthhorseman.net>\r
+References: <1467970047-8013-1-git-send-email-dkg@fifthhorseman.net>\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.20\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <https://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch/>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <https://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Fri, 08 Jul 2016 10:15:53 -0000\r
+\r
+If we see index options that ask us to decrypt when indexing a\r
+message, and we encounter an encrypted part, we'll try to descend into\r
+it.\r
+\r
+If we can decrypt, we add the property index-decryption=success.\r
+\r
+If we can't decrypt (or recognize the encrypted type of mail), we add\r
+the property index-decryption=failure.\r
+\r
+Note that a single message may have both values of the\r
+"index-decryption" property: "success" and "failure". For example,\r
+consider a message that includes multiple layers of encryption. If we\r
+manage to decrypt the outer layer ("index-decryption=success"), but\r
+fail on the inner layer ("index-decryption=failure").\r
+---\r
+ lib/database.cc | 3 ++-\r
+ lib/index.cc | 74 ++++++++++++++++++++++++++++++++++++++++++++++++---\r
+ lib/notmuch-private.h | 1 +\r
+ 3 files changed, 74 insertions(+), 4 deletions(-)\r
+\r
+diff --git a/lib/database.cc b/lib/database.cc\r
+index 9d6b6f2..4e01f12 100644\r
+--- a/lib/database.cc\r
++++ b/lib/database.cc\r
+@@ -2426,6 +2426,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+ notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS, ret2;\r
+ notmuch_private_status_t private_status;\r
+ notmuch_bool_t is_ghost = false;\r
++ notmuch_indexopts_t *indexopts = NULL;\r
+ \r
+ const char *date, *header;\r
+ const char *from, *to, *subject;\r
+@@ -2538,7 +2539,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+ date = _notmuch_message_file_get_header (message_file, "date");\r
+ _notmuch_message_set_header_values (message, date, from, subject);\r
+ \r
+- ret = _notmuch_message_index_file (message, message_file);\r
++ ret = _notmuch_message_index_file (message, indexopts, message_file);\r
+ if (ret)\r
+ goto DONE;\r
+ } else {\r
+diff --git a/lib/index.cc b/lib/index.cc\r
+index 1c030a6..a579c42 100644\r
+--- a/lib/index.cc\r
++++ b/lib/index.cc\r
+@@ -300,9 +300,14 @@ _index_address_list (notmuch_message_t *message,\r
+ }\r
+ }\r
+ \r
++static void\r
++_index_encrypted_mime_part (notmuch_message_t *message, notmuch_indexopts_t *indexopts,\r
++ GMimeContentType *content_type, GMimeMultipartEncrypted *part);\r
++\r
+ /* Callback to generate terms for each mime part of a message. */\r
+ static void\r
+ _index_mime_part (notmuch_message_t *message,\r
++ notmuch_indexopts_t *indexopts,\r
+ GMimeObject *part)\r
+ {\r
+ GMimeStream *stream, *filter;\r
+@@ -340,17 +345,19 @@ _index_mime_part (notmuch_message_t *message,\r
+ /* FIXME: is it always just the first part that is signed in\r
+ all multipart/signed messages?*/\r
+ _index_mime_part (message,\r
++ indexopts,\r
+ g_mime_multipart_get_part (multipart, 0));\r
+ \r
+ if (g_mime_multipart_get_count (multipart) > 2)\r
+ _notmuch_database_log (_notmuch_message_database (message),\r
+ "Warning: Unexpected extra parts of multipart/signed. Indexing anyway.\n");\r
+ } else if (GMIME_IS_MULTIPART_ENCRYPTED (multipart)) {\r
+- /* Don't index encrypted parts */\r
+ _notmuch_message_add_term (message, "tag", "encrypted");\r
++ _index_encrypted_mime_part(message, indexopts, content_type, GMIME_MULTIPART_ENCRYPTED (part));\r
+ } else {\r
+ for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {\r
+ _index_mime_part (message,\r
++ indexopts,\r
+ g_mime_multipart_get_part (multipart, i));\r
+ }\r
+ }\r
+@@ -362,7 +369,7 @@ _index_mime_part (notmuch_message_t *message,\r
+ \r
+ mime_message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (part));\r
+ \r
+- _index_mime_part (message, g_mime_message_get_mime_part (mime_message));\r
++ _index_mime_part (message, indexopts, g_mime_message_get_mime_part (mime_message));\r
+ \r
+ return;\r
+ }\r
+@@ -432,8 +439,69 @@ _index_mime_part (notmuch_message_t *message,\r
+ }\r
+ }\r
+ \r
++/* descend (if desired) into the cleartext part of an encrypted MIME\r
++ * part while indexing. */\r
++static void\r
++_index_encrypted_mime_part (notmuch_message_t *message,\r
++ notmuch_indexopts_t *indexopts,\r
++ GMimeContentType *content_type,\r
++ GMimeMultipartEncrypted *encrypted_data)\r
++{\r
++ notmuch_status_t status;\r
++ GMimeCryptoContext* crypto_ctx = NULL;\r
++ const char *protocol = NULL;\r
++ GError *err = NULL;\r
++ notmuch_database_t * notmuch = NULL;\r
++ GMimeObject *clear = NULL;\r
++\r
++ if (!indexopts || !notmuch_indexopts_get_try_decrypt (indexopts))\r
++ return;\r
++\r
++ protocol = g_mime_content_type_get_parameter (content_type, "protocol");\r
++ notmuch = _notmuch_message_database (message);\r
++ \r
++ status = _notmuch_crypto_get_gmime_ctx_for_protocol (&(indexopts->crypto),\r
++ protocol, &crypto_ctx);\r
++ if (status) {\r
++ _notmuch_database_log (notmuch, "Warning: setup failed for decrypting "\r
++ "during indexing. (%d)\n", status);\r
++ status = notmuch_message_add_property (message, "index-decryption", "failure");\r
++ if (status)\r
++ _notmuch_database_log (notmuch, "failed to add index-decryption "\r
++ "property (%d)\n", status);\r
++ return;\r
++ }\r
++\r
++ /* we don't need the GMimeDecryptResult, because we're not looking\r
++ * at validating signatures, and we don't care about indexing who\r
++ * the message was ostensibly encrypted to.\r
++ */\r
++ clear = g_mime_multipart_encrypted_decrypt(encrypted_data, crypto_ctx,\r
++ NULL, &err);\r
++ if (err) {\r
++ _notmuch_database_log (notmuch, "Failed to decrypt during indexing. (%d:%d) [%s]\n",\r
++ err->domain, err->code, err->message);\r
++ g_error_free(err);\r
++ /* Indicate that we failed to decrypt during indexing */\r
++ status = notmuch_message_add_property (message, "index-decryption", "failure");\r
++ if (status)\r
++ _notmuch_database_log (notmuch, "failed to add index-decryption "\r
++ "property (%d)\n", status);\r
++ return;\r
++ }\r
++ _index_mime_part (message, indexopts, clear);\r
++ g_object_unref (clear);\r
++ \r
++ status = notmuch_message_add_property (message, "index-decryption", "success");\r
++ if (status)\r
++ _notmuch_database_log (notmuch, "failed to add index-decryption "\r
++ "property (%d)\n", status);\r
++\r
++}\r
++\r
+ notmuch_status_t\r
+ _notmuch_message_index_file (notmuch_message_t *message,\r
++ notmuch_indexopts_t *indexopts,\r
+ notmuch_message_file_t *message_file)\r
+ {\r
+ GMimeMessage *mime_message;\r
+@@ -463,7 +531,7 @@ _notmuch_message_index_file (notmuch_message_t *message,\r
+ subject = g_mime_message_get_subject (mime_message);\r
+ _notmuch_message_gen_terms (message, "subject", subject);\r
+ \r
+- _index_mime_part (message, g_mime_message_get_mime_part (mime_message));\r
++ _index_mime_part (message, indexopts, g_mime_message_get_mime_part (mime_message));\r
+ \r
+ return NOTMUCH_STATUS_SUCCESS;\r
+ }\r
+diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h\r
+index 8b2aede..01b65ba 100644\r
+--- a/lib/notmuch-private.h\r
++++ b/lib/notmuch-private.h\r
+@@ -431,6 +431,7 @@ _notmuch_message_file_get_header (notmuch_message_file_t *message,\r
+ \r
+ notmuch_status_t\r
+ _notmuch_message_index_file (notmuch_message_t *message,\r
++ notmuch_indexopts_t *indexopts,\r
+ notmuch_message_file_t *message_file);\r
+ \r
+ /* messages.c */\r
+-- \r
+2.8.1\r
+\r