From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by arlo.cworth.org (Postfix) with ESMTP id E7D406DE0B6D for ; Mon, 11 Dec 2017 23:18:21 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at cworth.org X-Spam-Flag: NO X-Spam-Score: -0.027 X-Spam-Level: X-Spam-Status: No, score=-0.027 tagged_above=-999 required=5 tests=[AWL=-0.027] 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 WfvP5ryG--JK for ; Mon, 11 Dec 2017 23:18:17 -0800 (PST) Received: from che.mayfirst.org (che.mayfirst.org [162.247.75.118]) by arlo.cworth.org (Postfix) with ESMTPS id C62A66DE0941 for ; Mon, 11 Dec 2017 23:18:16 -0800 (PST) Received: from fifthhorseman.net (unknown [38.109.115.130]) by che.mayfirst.org (Postfix) with ESMTPSA id 6C9C0F99B for ; Tue, 12 Dec 2017 02:18:16 -0500 (EST) Received: by fifthhorseman.net (Postfix, from userid 1000) id 42AFC201A9; Tue, 12 Dec 2017 02:18:13 -0500 (EST) From: Daniel Kahn Gillmor To: Notmuch Mail Subject: [PATCH 1/5] crypto: prepare for decryption of inline PGP encrypted messages Date: Tue, 12 Dec 2017 02:15:49 -0500 Message-Id: <20171212071553.6440-2-dkg@fifthhorseman.net> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20171212071553.6440-1-dkg@fifthhorseman.net> References: <20171212071553.6440-1-dkg@fifthhorseman.net> X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.23 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: Tue, 12 Dec 2017 07:18:22 -0000 Inline PGP encrypted messages are clearly worse than PGP/MIME structured encrypted messages. There are no standards for how they are formed, and they don't offer any structured metadata about how to interpret the bytestream produced by decrypting them. However, some other MUAs and end-user workflows may make creation of inline PGP encrypted messages the only available option for message encryption, and when Notmuch encounters such a message, it should make a reasonable best-effort to render the cleartext to the user. Due to ambiguities in interpretation of signatures on inline messages (e.g. which parts of the message were actually signed? what character encoding should the bytestream be interpreted as), we continue to ignore inline-signed messages entirely, and we do not look at the validity of any signatures that might be found when decrypting inline PGP encrypted messages. We make use here of GMime's optimization function for detecting the presence of inline PGP encrypted content, which is only found in GMime 3.0 or later. This change prepares the internal codebase for decrypting inline encrypted messages, but does not yet actually use the capability. --- lib/index.cc | 6 +++--- mime-node.c | 24 ++++++++++++++---------- util/crypto.c | 35 +++++++++++++++++++++++++++-------- util/crypto.h | 2 +- 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/lib/index.cc b/lib/index.cc index 22ca9ec1..f144b9fb 100644 --- a/lib/index.cc +++ b/lib/index.cc @@ -367,7 +367,7 @@ _index_content_type (notmuch_message_t *message, GMimeObject *part) static void _index_encrypted_mime_part (notmuch_message_t *message, notmuch_indexopts_t *indexopts, GMimeContentType *content_type, - GMimeMultipartEncrypted *part); + GMimeObject *part); /* Callback to generate terms for each mime part of a message. */ static void @@ -421,7 +421,7 @@ _index_mime_part (notmuch_message_t *message, if (i == GMIME_MULTIPART_ENCRYPTED_CONTENT) { _index_encrypted_mime_part(message, indexopts, content_type, - GMIME_MULTIPART_ENCRYPTED (part)); + part); } else { if (i != GMIME_MULTIPART_ENCRYPTED_VERSION) { _notmuch_database_log (notmuch_message_get_database (message), @@ -518,7 +518,7 @@ static void _index_encrypted_mime_part (notmuch_message_t *message, notmuch_indexopts_t *indexopts, g_mime_3_unused(GMimeContentType *content_type), - GMimeMultipartEncrypted *encrypted_data) + GMimeObject *encrypted_data) { notmuch_status_t status; GError *err = NULL; diff --git a/mime-node.c b/mime-node.c index 75b79f98..973133d9 100644 --- a/mime-node.c +++ b/mime-node.c @@ -196,10 +196,10 @@ node_decrypt_and_verify (mime_node_t *node, GMimeObject *part, { GError *err = NULL; GMimeDecryptResult *decrypt_result = NULL; - GMimeMultipartEncrypted *encrypteddata = GMIME_MULTIPART_ENCRYPTED (part); notmuch_message_t *message = NULL; - if (! node->decrypted_child) { + if (GMIME_IS_PART (part) || /* must be inline */ + (GMIME_IS_MULTIPART_ENCRYPTED (part) && ! node->decrypted_child)) { for (mime_node_t *parent = node; parent; parent = parent->parent) if (parent->envelope_file) { message = parent->envelope_file; @@ -209,7 +209,7 @@ node_decrypt_and_verify (mime_node_t *node, GMimeObject *part, node->decrypted_child = _notmuch_crypto_decrypt (&node->decrypt_attempted, node->ctx->crypto->decrypt, message, - cryptoctx, encrypteddata, &decrypt_result, &err); + cryptoctx, part, &decrypt_result, &err); } if (! node->decrypted_child) { fprintf (stderr, "Failed to decrypt part: %s\n", @@ -217,15 +217,19 @@ node_decrypt_and_verify (mime_node_t *node, GMimeObject *part, goto DONE; } - node->decrypt_success = true; - node->verify_attempted = true; if (decrypt_result) { - /* This may be NULL if the part is not signed. */ - node->sig_list = g_mime_decrypt_result_get_signatures (decrypt_result); - if (node->sig_list) { - g_object_ref (node->sig_list); - set_signature_list_destructor (node); + node->decrypt_success = true; + if (GMIME_IS_MULTIPART_ENCRYPTED (part)) { + /* Only check signatures on PGP/MIME messages, not inline + messages. To understand why, see + https://dkg.fifthhorseman.net/notes/inline-pgp-harmful/ */ + node->verify_attempted = true; + node->sig_list = g_mime_decrypt_result_get_signatures (decrypt_result); + if (node->sig_list) { + g_object_ref (node->sig_list); + set_signature_list_destructor (node); + } } #if HAVE_GMIME_SESSION_KEYS diff --git a/util/crypto.c b/util/crypto.c index 9d3b6dad..7965ab8e 100644 --- a/util/crypto.c +++ b/util/crypto.c @@ -144,7 +144,7 @@ _notmuch_crypto_decrypt (bool *attempted, notmuch_decryption_policy_t decrypt, notmuch_message_t *message, g_mime_3_unused(GMimeCryptoContext* crypto_ctx), - GMimeMultipartEncrypted *part, + GMimeObject *part, GMimeDecryptResult **decrypt_result, GError **err) { @@ -166,15 +166,26 @@ _notmuch_crypto_decrypt (bool *attempted, if (attempted) *attempted = true; #if (GMIME_MAJOR_VERSION < 3) - ret = g_mime_multipart_encrypted_decrypt_session (part, + ret = g_mime_multipart_encrypted_decrypt_session (GMIME_MULTIPART_ENCRYPTED (part), crypto_ctx, notmuch_message_properties_value (list), decrypt_result, err); #else - ret = g_mime_multipart_encrypted_decrypt (part, - GMIME_DECRYPT_NONE, - notmuch_message_properties_value (list), - decrypt_result, err); + if (GMIME_IS_MULTIPART_ENCRYPTED (part)) { + ret = g_mime_multipart_encrypted_decrypt (GMIME_MULTIPART_ENCRYPTED (part), + GMIME_DECRYPT_NONE, + notmuch_message_properties_value (list), + decrypt_result, err); + } else if (GMIME_IS_PART (part) && g_mime_part_get_openpgp_data (GMIME_PART (part)) == GMIME_OPENPGP_DATA_ENCRYPTED) { + *decrypt_result = g_mime_part_openpgp_decrypt (GMIME_PART (part), + GMIME_DECRYPT_NONE, + notmuch_message_properties_value (list), + err); + if (decrypt_result) { + ret = part; + g_object_ref (ret); + } + } #endif if (ret) break; @@ -214,8 +225,16 @@ _notmuch_crypto_decrypt (bool *attempted, GMimeDecryptFlags flags = GMIME_DECRYPT_NONE; if (decrypt == NOTMUCH_DECRYPT_TRUE && decrypt_result) flags |= GMIME_DECRYPT_EXPORT_SESSION_KEY; - ret = g_mime_multipart_encrypted_decrypt(part, flags, NULL, - decrypt_result, err); + if (GMIME_IS_MULTIPART_ENCRYPTED (part)) { + ret = g_mime_multipart_encrypted_decrypt(GMIME_MULTIPART_ENCRYPTED (part), flags, NULL, + decrypt_result, err); + } else if (GMIME_IS_PART (part) && g_mime_part_get_openpgp_data (GMIME_PART (part)) == GMIME_OPENPGP_DATA_ENCRYPTED) { + *decrypt_result = g_mime_part_openpgp_decrypt (GMIME_PART (part), flags, NULL, err); + if (decrypt_result) { + ret = part; + g_object_ref (ret); + } + } #endif return ret; } diff --git a/util/crypto.h b/util/crypto.h index c384601c..d9e4a1c7 100644 --- a/util/crypto.h +++ b/util/crypto.h @@ -20,7 +20,7 @@ _notmuch_crypto_decrypt (bool *attempted, notmuch_decryption_policy_t decrypt, notmuch_message_t *message, GMimeCryptoContext* crypto_ctx, - GMimeMultipartEncrypted *part, + GMimeObject *part, GMimeDecryptResult **decrypt_result, GError **err); -- 2.15.1