Re: [PATCH v2 1/9] lib: index PKCS7 SignedData parts

2020-05-23 Thread David Bremner
Daniel Kahn Gillmor  writes:

> When we are indexing, we should treat SignedData parts the same way
> that we treat a multipart object, indexing the wrapped part as a
> distinct MIME object.
>

series pushed

d
___
notmuch mailing list
notmuch@notmuchmail.org
https://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v2 1/9] lib: index PKCS7 SignedData parts

2020-05-12 Thread Daniel Kahn Gillmor
When we are indexing, we should treat SignedData parts the same way
that we treat a multipart object, indexing the wrapped part as a
distinct MIME object.

Unfortunately, this means doing some sort of cryptographic
verification whose results we throw away, because GMime doesn't offer
us any way to unwrap without doing signature verification.

I've opened https://github.com/jstedfast/gmime/issues/67 to request
the capability from GMime but for now, we'll just accept the
additional performance hit.

As we do this indexing, we also apply the "signed" tag, by analogy
with how we handle multipart/signed messages.  These days, that kind
of change should probably be done with a property instead, but that's
a different set of changes.  This one is just for consistency.

Note that we are currently *only* handling signedData parts, which are
basically clearsigned messages.  PKCS#7 parts can also be
envelopedData and authEnvelopedData (which are effectively encryption
layers), and compressedData (which afaict isn't implemented anywhere,
i've never encountered it).  We're laying the groundwork for indexing
these other S/MIME types here, but we're only dealing with signedData
for now.

Signed-off-by: Daniel Kahn Gillmor 
---
 lib/index.cc   | 57 ++
 test/T355-smime.sh |  2 --
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/lib/index.cc b/lib/index.cc
index 158ba5cf..bbf13dc5 100644
--- a/lib/index.cc
+++ b/lib/index.cc
@@ -372,6 +372,12 @@ _index_encrypted_mime_part (notmuch_message_t *message, 
notmuch_indexopts_t *ind
GMimeMultipartEncrypted *part,
_notmuch_message_crypto_t *msg_crypto);
 
+static void
+_index_pkcs7_part (notmuch_message_t *message,
+  notmuch_indexopts_t *indexopts,
+  GMimeObject *part,
+  _notmuch_message_crypto_t *msg_crypto);
+
 /* Callback to generate terms for each mime part of a message. */
 static void
 _index_mime_part (notmuch_message_t *message,
@@ -466,6 +472,11 @@ _index_mime_part (notmuch_message_t *message,
goto DONE;
 }
 
+if (GMIME_IS_APPLICATION_PKCS7_MIME (part)) {
+   _index_pkcs7_part (message, indexopts, part, msg_crypto);
+   goto DONE;
+}
+
 if (! (GMIME_IS_PART (part))) {
_notmuch_database_log (notmuch_message_get_database (message),
   "Warning: Not indexing unknown mime part: %s.\n",
@@ -608,6 +619,52 @@ _index_encrypted_mime_part (notmuch_message_t *message,
 
 }
 
+static void
+_index_pkcs7_part (notmuch_message_t *message,
+  notmuch_indexopts_t *indexopts,
+  GMimeObject *part,
+  _notmuch_message_crypto_t *msg_crypto)
+{
+GMimeApplicationPkcs7Mime *pkcs7;
+GMimeSecureMimeType p7type;
+GMimeObject *mimeobj = NULL;
+GMimeSignatureList *sigs = NULL;
+GError *err = NULL;
+notmuch_database_t *notmuch = NULL;
+
+pkcs7 = GMIME_APPLICATION_PKCS7_MIME (part);
+p7type = g_mime_application_pkcs7_mime_get_smime_type (pkcs7);
+notmuch = notmuch_message_get_database (message);
+_index_content_type (message, part);
+
+if (p7type == GMIME_SECURE_MIME_TYPE_SIGNED_DATA) {
+   sigs = g_mime_application_pkcs7_mime_verify (pkcs7, GMIME_VERIFY_NONE, 
, );
+   if (sigs == NULL) {
+   _notmuch_database_log (notmuch, "Failed to verify PKCS#7 SignedData 
during indexing. (%d:%d) [%s]\n",
+  err->domain, err->code, err->message);
+   g_error_free (err);
+   goto DONE;
+   }
+   _notmuch_message_add_term (message, "tag", "signed");
+   GMimeObject *toindex = mimeobj;
+   if (_notmuch_message_crypto_potential_payload (msg_crypto, mimeobj, 
part, 0) &&
+   msg_crypto->decryption_status == NOTMUCH_MESSAGE_DECRYPTED_FULL) {
+   toindex = _notmuch_repair_crypto_payload_skip_legacy_display 
(mimeobj);
+   if (toindex != mimeobj)
+   notmuch_message_add_property (message, "index.repaired", 
"skip-protected-headers-legacy-display");
+   }
+   _index_mime_part (message, indexopts, toindex, msg_crypto);
+} else {
+   _notmuch_database_log (notmuch, "Cannot currently handle PKCS#7 
smime-type '%s'\n",
+  g_mime_object_get_content_type_parameter (part, 
"smime-type"));
+}
+ DONE:
+if (mimeobj)
+   g_object_unref (mimeobj);
+if (sigs)
+   g_object_unref (sigs);
+}
+
 static notmuch_status_t
 _notmuch_message_index_user_headers (notmuch_message_t *message, GMimeMessage 
*mime_message)
 {
diff --git a/test/T355-smime.sh b/test/T355-smime.sh
index f8e8e396..a7eecedf 100755
--- a/test/T355-smime.sh
+++ b/test/T355-smime.sh
@@ -132,13 +132,11 @@ expected=''
 test_expect_equal "$expected" "$output"
 
 test_begin_subtest "know the MIME type of the embedded part in PKCS#7 
SignedData"
-test_subtest_known_broken