diff --git a/completion/notmuch-completion.bash b/completion/notmuch-completion.bash index 249b9664..15425697 100644 --- a/completion/notmuch-completion.bash +++ b/completion/notmuch-completion.bash @@ -522,7 +522,7 @@ _notmuch_show() return ;; --decrypt) - COMPREPLY=( $( compgen -W "true auto false" -- "${cur}" ) ) + COMPREPLY=( $( compgen -W "true auto false stash" -- "${cur}" ) ) return ;; esac diff --git a/doc/man1/notmuch-show.rst b/doc/man1/notmuch-show.rst index 2b825ccc..b2667537 100644 --- a/doc/man1/notmuch-show.rst +++ b/doc/man1/notmuch-show.rst @@ -110,7 +110,7 @@ Supported options for **show** include supported with --format=json and --format=sexp), and the multipart/signed part will be replaced by the signed data. -``--decrypt=(false|auto|true)`` +``--decrypt=(false|auto|true|stash)`` If ``true``, decrypt any MIME encrypted parts found in the selected content (i.e. "multipart/encrypted" parts). Status of the decryption will be reported (currently only supported @@ -118,17 +118,45 @@ Supported options for **show** include decryption the multipart/encrypted part will be replaced by the decrypted content. + ``stash`` behaves like ``true``, but upon successful decryption it + will also stash the message's session key in the database, and + index the cleartext of the message, enabling automatic decryption + in the future. + If ``auto``, and a session key is already known for the message, then it will be decrypted, but notmuch will not try to access the user's keys. Use ``false`` to avoid even automatic decryption. - Non-automatic decryption expects a functioning - **gpg-agent(1)** to provide any needed credentials. Without - one, the decryption will fail. + Non-automatic decryption (``stash`` or ``true``, in the absence of + a stashed session key) expects a functioning **gpg-agent(1)** to + provide any needed credentials. Without one, the decryption will + fail. - Note: ``true`` implies --verify. + Note: setting either ``true`` or ``stash`` here implies + ``--verify``. + + Here is a table that summarizes each of these policies: + + +------------------------+-------+------+------+-------+ + | | false | auto | true | stash | + +========================+=======+======+======+=======+ + | Show cleartext if | | X | X | X | + | session key is | | | | | + | already known | | | | | + +------------------------+-------+------+------+-------+ + | Use secret keys to | | | X | X | + | show cleartext | | | | | + +------------------------+-------+------+------+-------+ + | Stash any newly | | | | X | + | recovered session keys,| | | | | + | reindexing message if | | | | | + | found | | | | | + +------------------------+-------+------+------+-------+ + + Note: ``--decrypt=stash`` requires write access to the database. + Otherwise, ``notmuch show`` operates entirely in read-only mode. Default: ``auto`` diff --git a/notmuch-show.c b/notmuch-show.c index 3d10f3b2..1072ea55 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -1124,6 +1124,7 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[]) (notmuch_keyword_t []){ { "false", NOTMUCH_DECRYPT_FALSE }, { "auto", NOTMUCH_DECRYPT_AUTO }, { "true", NOTMUCH_DECRYPT_NOSTASH }, + { "stash", NOTMUCH_DECRYPT_TRUE }, { 0, 0 } } }, { .opt_bool = ¶ms.crypto.verify, .name = "verify" }, { .opt_bool = ¶ms.output_body, .name = "body" }, @@ -1139,7 +1140,8 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[]) notmuch_process_shared_options (argv[0]); /* explicit decryption implies verification */ - if (params.crypto.decrypt == NOTMUCH_DECRYPT_NOSTASH) + if (params.crypto.decrypt == NOTMUCH_DECRYPT_NOSTASH || + params.crypto.decrypt == NOTMUCH_DECRYPT_TRUE) params.crypto.verify = true; /* specifying a part implies single message display */ @@ -1202,8 +1204,11 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[]) params.crypto.gpgpath = notmuch_config_get_crypto_gpg_path (config); #endif + notmuch_database_mode_t mode = NOTMUCH_DATABASE_MODE_READ_ONLY; + if (params.crypto.decrypt == NOTMUCH_DECRYPT_TRUE) + mode = NOTMUCH_DATABASE_MODE_READ_WRITE; if (notmuch_database_open (notmuch_config_get_database_path (config), - NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) + mode, ¬much)) return EXIT_FAILURE; notmuch_exit_if_unmatched_db_uuid (notmuch); diff --git a/test/T357-index-decryption.sh b/test/T357-index-decryption.sh index ad6c3616..c5435f4f 100755 --- a/test/T357-index-decryption.sh +++ b/test/T357-index-decryption.sh @@ -80,6 +80,24 @@ test_expect_equal \ "$output" \ "$expected" +# show the message using stashing decryption +test_begin_subtest "stash decryption during show" +output=$(notmuch show --decrypt=stash tag:encrypted subject:002 | notmuch_show_part 3) +expected='This is a test encrypted message with a wumpus.' +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "search should now find the contents" +output=$(notmuch search wumpus) +expected='thread:0000000000000003 2000-01-01 [1/1] Notmuch Test Suite; test encrypted message for cleartext index 002 (encrypted inbox unread)' +if [ $NOTMUCH_HAVE_GMIME_SESSION_KEYS -eq 0 ]; then + test_subtest_known_broken +fi +test_expect_equal \ + "$output" \ + "$expected" + # try reinserting it with decryption, should appear again, but now we # have two copies of the message: test_begin_subtest "message cleartext is present after reinserting with --decrypt=true"