util/crypto: add information about the payload part
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Sun, 26 May 2019 22:15:55 +0000 (18:15 -0400)
committerDavid Bremner <david@tethera.net>
Wed, 29 May 2019 11:02:45 +0000 (08:02 -0300)
When walking the MIME tree, if we discover that we are at the
cryptographic payload, then we would like to record at least the
Subject header of the current MIME part.

In the future, we might want to record many other headers as well, but
for now we will stick with just the Subject.

See
https://dkg.fifthhorseman.net/blog/e-mail-cryptography.html#cryptographic-envelope
for more description of the Cryptographic Payload vs. the
Cryptographic Envelope.

Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
util/crypto.c
util/crypto.h

index 3f8ac25a0cd952eb5e62dddf2ce3ef2b556cc693..9e185e036573c90a5be0ee983d338d8fbf994c2f 100644 (file)
@@ -90,6 +90,8 @@ _notmuch_message_crypto_destructor (_notmuch_message_crypto_t *msg_crypto)
        return 0;
     if (msg_crypto->sig_list)
        g_object_unref (msg_crypto->sig_list);
+    if (msg_crypto->payload_subject)
+       talloc_free (msg_crypto->payload_subject);
     return 0;
 }
 
@@ -133,6 +135,10 @@ _notmuch_message_crypto_potential_sig_list (_notmuch_message_crypto_t *msg_crypt
 notmuch_status_t
 _notmuch_message_crypto_potential_payload (_notmuch_message_crypto_t *msg_crypto, GMimeObject *payload, GMimeObject *parent, int childnum)
 {
+    const char *protected_headers = NULL;
+    const char *forwarded = NULL;
+    const char *subject = NULL;
+
     if (!msg_crypto || !payload)
        return NOTMUCH_STATUS_NULL_POINTER;
 
@@ -156,6 +162,37 @@ _notmuch_message_crypto_potential_payload (_notmuch_message_crypto_t *msg_crypto
 
     msg_crypto->payload_encountered = true;
 
+    /* don't bother recording anything if there is no cryptographic
+     * envelope: */
+    if ((msg_crypto->decryption_status != NOTMUCH_MESSAGE_DECRYPTED_FULL) &&
+       (msg_crypto->sig_list == NULL))
+       return NOTMUCH_STATUS_SUCCESS;
+
+    /* Verify that this payload has headers that are intended to be
+     * exported to the larger message: */
+
+    /* Consider a payload that uses Alexei Melinkov's forwarded="no" for
+     * message/global or message/rfc822:
+     * https://tools.ietf.org/html/draft-melnikov-smime-header-signing-05#section-4 */
+    forwarded = g_mime_object_get_content_type_parameter (payload, "forwarded");
+    if (GMIME_IS_MESSAGE_PART (payload) && forwarded && strcmp (forwarded, "no") == 0) {
+       GMimeMessage *message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (payload));
+       subject = g_mime_message_get_subject (message);
+       /* FIXME: handle more than just Subject: at some point */
+    } else {
+       /* Consider "memoryhole"-style protected headers as practiced by Enigmail and K-9 */
+       protected_headers = g_mime_object_get_content_type_parameter (payload, "protected-headers");
+       if (protected_headers && strcasecmp("v1", protected_headers) == 0)
+           subject = g_mime_object_get_header (payload, "Subject");
+       /* FIXME: handle more than just Subject: at some point */
+    }
+
+    if (subject) {
+       if (msg_crypto->payload_subject)
+           talloc_free (msg_crypto->payload_subject);
+       msg_crypto->payload_subject = talloc_strdup (msg_crypto, subject);
+    }
+
     return NOTMUCH_STATUS_SUCCESS;
 }
 
index c6fa7f4b76578b63d5f6aa1008b58cf10ec3b64c..fdbb5da5d49de736f2d991f7b8d6e24e6af78aa4 100644 (file)
@@ -59,6 +59,11 @@ typedef struct _notmuch_message_crypto {
      * is not part of the cryptographic envelope) */
     bool payload_encountered;
 
+    /* the value of any "Subject:" header in the cryptographic payload
+     * (the top level part within the crypto envelope), converted to
+     * UTF-8 */
+    char * payload_subject;
+
     /* if both signed and encrypted, was the signature encrypted? */
     bool signature_encrypted;
 } _notmuch_message_crypto_t;