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 538ED6DE1003 for ; Thu, 30 Nov 2017 01:00:00 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at cworth.org X-Spam-Flag: NO X-Spam-Score: -0.015 X-Spam-Level: X-Spam-Status: No, score=-0.015 tagged_above=-999 required=5 tests=[AWL=-0.015] 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 v382qmCQPbdV for ; Thu, 30 Nov 2017 00:59:59 -0800 (PST) Received: from che.mayfirst.org (che.mayfirst.org [162.247.75.118]) by arlo.cworth.org (Postfix) with ESMTPS id 685776DE0B3B for ; Thu, 30 Nov 2017 00:59:57 -0800 (PST) Received: from fifthhorseman.net (ool-6c3a0662.static.optonline.net [108.58.6.98]) by che.mayfirst.org (Postfix) with ESMTPSA id CA9F6F99F for ; Thu, 30 Nov 2017 03:59:56 -0500 (EST) Received: by fifthhorseman.net (Postfix, from userid 1000) id 3D2CD2173D; Thu, 30 Nov 2017 03:59:53 -0500 (EST) From: Daniel Kahn Gillmor To: Notmuch Mail Subject: [PATCH v2 19/21] crypto: add --decrypt=nostash to avoid stashing session keys Date: Thu, 30 Nov 2017 03:59:44 -0500 Message-Id: <20171130085946.11332-20-dkg@fifthhorseman.net> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20171130085946.11332-1-dkg@fifthhorseman.net> References: <20171130085946.11332-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: Thu, 30 Nov 2017 09:00:00 -0000 Here's the configuration choice for people who want a cleartext index, but don't want stashed session keys. Interestingly, this "nostash" decryption policy is actually the same policy that should be used by "notmuch show" and "notmuch reply", since they never modify the index or database when they are invoked with --decrypt. We take advantage of this parallel to tune the behavior of those programs so that we're not requesting session keys from GnuPG during "show" and "reply" that we would then otherwise just throw away. --- completion/notmuch-completion.bash | 6 +++--- doc/man1/notmuch-config.rst | 17 ++++++++++++----- doc/man1/notmuch-insert.rst | 16 ++++++++++------ doc/man1/notmuch-new.rst | 7 ++++--- doc/man1/notmuch-reindex.rst | 16 ++++++++++------ lib/indexopts.c | 2 ++ lib/notmuch.h | 1 + notmuch-reply.c | 2 +- notmuch-show.c | 3 ++- notmuch.c | 1 + test/T357-index-decryption.sh | 23 +++++++++++++++++++++++ util/crypto.c | 4 ++-- 12 files changed, 71 insertions(+), 27 deletions(-) diff --git a/completion/notmuch-completion.bash b/completion/notmuch-completion.bash index 272131e6..948c153b 100644 --- a/completion/notmuch-completion.bash +++ b/completion/notmuch-completion.bash @@ -288,7 +288,7 @@ _notmuch_insert() return ;; --decrypt) - COMPREPLY=( $( compgen -W "true false auto" -- "${cur}" ) ) + COMPREPLY=( $( compgen -W "true false auto nostash" -- "${cur}" ) ) return ;; esac @@ -320,7 +320,7 @@ _notmuch_new() $split && case "${prev}" in --decrypt) - COMPREPLY=( $( compgen -W "true false auto" -- "${cur}" ) ) + COMPREPLY=( $( compgen -W "true false auto nostash" -- "${cur}" ) ) return ;; esac @@ -442,7 +442,7 @@ _notmuch_reindex() $split && case "${prev}" in --decrypt) - COMPREPLY=( $( compgen -W "true false auto" -- "${cur}" ) ) + COMPREPLY=( $( compgen -W "true false auto nostash" -- "${cur}" ) ) return ;; esac diff --git a/doc/man1/notmuch-config.rst b/doc/man1/notmuch-config.rst index dabf269f..773fd9da 100644 --- a/doc/man1/notmuch-config.rst +++ b/doc/man1/notmuch-config.rst @@ -141,6 +141,9 @@ The available configuration items are described below. **index.decrypt** **[STORED IN DATABASE]** + + One of ``false``, ``auto``, ``nostash``, or ``true``. + When indexing an encrypted e-mail message, if this variable is set to ``true``, notmuch will try to decrypt the message and index the cleartext, stashing a copy of any discovered session @@ -150,11 +153,15 @@ The available configuration items are described below. secret keys. Use ``false`` to avoid decrypting even when a stashed session key is already present. - Be aware that the notmuch index is likely sufficient to - reconstruct the cleartext of the message itself, so please - ensure that the notmuch message index is adequately protected. - DO NOT USE ``index.decrypt=true`` without considering the - security of your index. + ``nostash`` is the same as ``true`` except that it will not + stash newly-discovered session keys in the database. + + Be aware that the notmuch index is likely sufficient (and a + stashed session key is certainly sufficient) to reconstruct + the cleartext of the message itself, so please ensure that the + notmuch message index is adequately protected. DO NOT USE + ``index.decrypt=true`` or ``index.decrypt=nostash`` without + considering the security of your index. Default: ``auto``. diff --git a/doc/man1/notmuch-insert.rst b/doc/man1/notmuch-insert.rst index 214f261b..1a3dfe98 100644 --- a/doc/man1/notmuch-insert.rst +++ b/doc/man1/notmuch-insert.rst @@ -51,10 +51,10 @@ Supported options for **insert** include ``--no-hooks`` Prevent hooks from being run. - ``--decrypt=(true|auto|false)`` + ``--decrypt=(true|nostash|auto|false)`` If ``true`` and the message is encrypted, try to decrypt the - message while indexing, storing any session keys discovered. + message while indexing, stashing any session keys discovered. If ``auto``, and notmuch already knows about a session key for the message, it will try decrypting using that session key but will not try to access the user's secret keys. If decryption @@ -62,11 +62,15 @@ Supported options for **insert** include message is always stored to disk in its original form (ciphertext). - Be aware that the index is likely sufficient to reconstruct - the cleartext of the message itself, so please ensure that the + ``nostash`` is the same as ``true`` except that it will not + stash newly-discovered session keys in the database. + + Be aware that the index is likely sufficient (and a stashed + session key is certainly sufficient) to reconstruct the + cleartext of the message itself, so please ensure that the notmuch message index is adequately protected. DO NOT USE - ``--decrypt=true`` without considering the security of - your index. + ``--decrypt=true`` or ``--decrypt=nostash`` without + considering the security of your index. See also ``index.decrypt`` in **notmuch-config(1)**. diff --git a/doc/man1/notmuch-new.rst b/doc/man1/notmuch-new.rst index 27676a19..3ddd4621 100644 --- a/doc/man1/notmuch-new.rst +++ b/doc/man1/notmuch-new.rst @@ -43,10 +43,10 @@ Supported options for **new** include ``--quiet`` Do not print progress or results. - ``--decrypt=(true|auto|false)`` + ``--decrypt=(true|nostash|auto|false)`` If ``true``, when encountering an encrypted message, try to - decrypt it while indexing, and store any discovered session + decrypt it while indexing, and stash any discovered session keys. If ``auto``, try to use any session key already known to belong to this message, but do not attempt to use the user's secret keys. If decryption is successful, index the @@ -56,7 +56,8 @@ Supported options for **new** include key is certainly sufficient) to reconstruct the cleartext of the message itself, so please ensure that the notmuch message index is adequately protected. DO NOT USE ``--decrypt=true`` - without considering the security of your index. + or ``--decrypt=nostash`` without considering the security of + your index. See also ``index.decrypt`` in **notmuch-config(1)**. diff --git a/doc/man1/notmuch-reindex.rst b/doc/man1/notmuch-reindex.rst index 47790871..8b3083cf 100644 --- a/doc/man1/notmuch-reindex.rst +++ b/doc/man1/notmuch-reindex.rst @@ -21,23 +21,27 @@ messages using the supplied options. Supported options for **reindex** include - ``--decrypt=(true|auto|false)`` + ``--decrypt=(true|nostash|auto|false)`` If ``true``, when encountering an encrypted message, try to - decrypt it while reindexing, storing any session keys + decrypt it while reindexing, stashing any session keys discovered. If ``auto``, and notmuch already knows about a session key for the message, it will try decrypting using that session key but will not try to access the user's secret keys. If decryption is successful, index the cleartext itself. + ``nostash`` is the same as ``true`` except that it will not + stash newly-discovered session keys in the database. + If ``false``, notmuch reindex will also delete any stashed session keys for all messages matching the search terms. - Be aware that the index is likely sufficient to reconstruct - the cleartext of the message itself, so please ensure that the + Be aware that the index is likely sufficient (and a stashed + session key is certainly sufficient) to reconstruct the + cleartext of the message itself, so please ensure that the notmuch message index is adequately protected. DO NOT USE - ``--decrypt=true`` without considering the security of your - index. + ``--decrypt=true`` or ``--decrypt=nostash`` without + considering the security of your index. See also ``index.decrypt`` in **notmuch-config(1)**. diff --git a/lib/indexopts.c b/lib/indexopts.c index 26a31e89..b78a57b6 100644 --- a/lib/indexopts.c +++ b/lib/indexopts.c @@ -42,6 +42,8 @@ notmuch_database_get_default_indexopts (notmuch_database_t *db) (!(strcasecmp(decrypt_policy, "no"))) || (!(strcasecmp(decrypt_policy, "0")))) notmuch_indexopts_set_decrypt_policy (ret, NOTMUCH_DECRYPT_FALSE); + else if (!strcasecmp(decrypt_policy, "nostash")) + notmuch_indexopts_set_decrypt_policy (ret, NOTMUCH_DECRYPT_NOSTASH); } free (decrypt_policy); diff --git a/lib/notmuch.h b/lib/notmuch.h index ff860e06..39759b7a 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -2242,6 +2242,7 @@ typedef enum { NOTMUCH_DECRYPT_FALSE, NOTMUCH_DECRYPT_TRUE, NOTMUCH_DECRYPT_AUTO, + NOTMUCH_DECRYPT_NOSTASH, } notmuch_decryption_policy_t; /** diff --git a/notmuch-reply.c b/notmuch-reply.c index fd990a9a..5cdf642b 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -730,7 +730,7 @@ notmuch_reply_command (notmuch_config_t *config, int argc, char *argv[]) notmuch_process_shared_options (argv[0]); if (decrypt_set) - params.crypto.decrypt = decrypt ? NOTMUCH_DECRYPT_TRUE : NOTMUCH_DECRYPT_FALSE; + params.crypto.decrypt = decrypt ? NOTMUCH_DECRYPT_NOSTASH : NOTMUCH_DECRYPT_FALSE; notmuch_exit_if_unsupported_format (); diff --git a/notmuch-show.c b/notmuch-show.c index 591889a9..2ad50007 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -1143,7 +1143,8 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[]) if (decrypt_set) { if (decrypt) { - params.crypto.decrypt = NOTMUCH_DECRYPT_TRUE; + /* we do not need or want to ask for session keys */ + params.crypto.decrypt = NOTMUCH_DECRYPT_NOSTASH; /* decryption implies verification */ params.crypto.verify = true; } else { diff --git a/notmuch.c b/notmuch.c index e18c05dd..057b9603 100644 --- a/notmuch.c +++ b/notmuch.c @@ -104,6 +104,7 @@ const notmuch_opt_desc_t notmuch_shared_indexing_options [] = { (notmuch_keyword_t []){ { "false", NOTMUCH_DECRYPT_FALSE }, { "true", NOTMUCH_DECRYPT_TRUE }, { "auto", NOTMUCH_DECRYPT_AUTO }, + { "nostash", NOTMUCH_DECRYPT_NOSTASH }, { 0, 0 } }, .name = "decrypt" }, { } diff --git a/test/T357-index-decryption.sh b/test/T357-index-decryption.sh index a3511a82..0c5da549 100755 --- a/test/T357-index-decryption.sh +++ b/test/T357-index-decryption.sh @@ -182,6 +182,29 @@ test_expect_equal \ "$output" \ "$expected" +test_begin_subtest "index cleartext without keeping session keys" +test_expect_success "notmuch reindex --decrypt=nostash tag:blarney" + +test_begin_subtest "Ensure that the indexed terms are present" +output=$(notmuch search wumpus) +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "show one of the messages with --decrypt" +output=$(notmuch show --decrypt thread:0000000000000001 | awk '/^\014part}/{ f=0 }; { if (f) { print $0 } } /^\014part{ ID: 3/{ f=1 }') +expected='This is a test encrypted message with a wumpus.' +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "Ensure that we cannot show the message without --decrypt" +output=$(notmuch show thread:0000000000000001 | awk '/^\014part}/{ f=0 }; { if (f) { print $0 } } /^\014part{ ID: 3/{ f=1 }') +expected='Non-text part: application/octet-stream' +test_expect_equal \ + "$output" \ + "$expected" + add_email_corpus crypto test_begin_subtest "indexing message fails when secret key not available" diff --git a/util/crypto.c b/util/crypto.c index 066dea6e..9d3b6dad 100644 --- a/util/crypto.c +++ b/util/crypto.c @@ -199,7 +199,7 @@ _notmuch_crypto_decrypt (bool *attempted, #if (GMIME_MAJOR_VERSION < 3) #if HAVE_GMIME_SESSION_KEYS gboolean oldgetsk = g_mime_crypto_context_get_retrieve_session_key (crypto_ctx); - gboolean newgetsk = (decrypt_result); + gboolean newgetsk = (decrypt == NOTMUCH_DECRYPT_TRUE && decrypt_result); if (newgetsk != oldgetsk) /* This could return an error, but we can't do anything about it, so ignore it */ g_mime_crypto_context_set_retrieve_session_key (crypto_ctx, newgetsk, NULL); @@ -212,7 +212,7 @@ _notmuch_crypto_decrypt (bool *attempted, #endif #else GMimeDecryptFlags flags = GMIME_DECRYPT_NONE; - if (decrypt_result) + 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); -- 2.15.0