cli/show: use decryption policy "auto" by default.

When showing a message, if the user doesn't specify --decrypt= at all,
but a stashed session key is known to notmuch, notmuch should just go
ahead and try to decrypt the message with the session key (without
bothering the user for access to their asymmetric secret key).

The user can disable this at the command line with --decrypt=false if
they really don't want to look at the e-mail that they've asked
notmuch to show them.

and of course, "notmuch show --decrypt" still works for accessing the
user's secret keys if necessary.
This commit is contained in:
Daniel Kahn Gillmor 2017-12-08 01:23:55 -05:00 committed by David Bremner
parent 6802b333eb
commit a1260896f6
4 changed files with 34 additions and 8 deletions

View file

@ -517,7 +517,7 @@ _notmuch_show()
COMPREPLY=( $( compgen -W "text json sexp mbox raw" -- "${cur}" ) ) COMPREPLY=( $( compgen -W "text json sexp mbox raw" -- "${cur}" ) )
return return
;; ;;
--exclude|--body) --exclude|--body|--decrypt)
COMPREPLY=( $( compgen -W "true false" -- "${cur}" ) ) COMPREPLY=( $( compgen -W "true false" -- "${cur}" ) )
return return
;; ;;
@ -526,7 +526,7 @@ _notmuch_show()
! $split && ! $split &&
case "${cur}" in case "${cur}" in
-*) -*)
local options="--entire-thread= --format= --exclude= --body= --format-version= --part= --verify --decrypt --include-html ${_notmuch_shared_options}" local options="--entire-thread= --format= --exclude= --body= --format-version= --part= --verify --decrypt= --include-html ${_notmuch_shared_options}"
compopt -o nospace compopt -o nospace
COMPREPLY=( $(compgen -W "$options" -- ${cur}) ) COMPREPLY=( $(compgen -W "$options" -- ${cur}) )
;; ;;

View file

@ -123,6 +123,10 @@ Supported options for **show** include
multipart/encrypted part will be replaced by the decrypted multipart/encrypted part will be replaced by the decrypted
content. content.
If a session key is already known for the message, then it
will be decrypted automatically unless the user explicitly
sets ``--decrypt=false``.
Decryption expects a functioning **gpg-agent(1)** to provide any Decryption expects a functioning **gpg-agent(1)** to provide any
needed credentials. Without one, the decryption will fail. needed credentials. Without one, the decryption will fail.

View file

@ -1083,13 +1083,14 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[])
.part = -1, .part = -1,
.omit_excluded = true, .omit_excluded = true,
.output_body = true, .output_body = true,
.crypto = { .decrypt = NOTMUCH_DECRYPT_FALSE }, .crypto = { .decrypt = NOTMUCH_DECRYPT_AUTO },
}; };
int format = NOTMUCH_FORMAT_NOT_SPECIFIED; int format = NOTMUCH_FORMAT_NOT_SPECIFIED;
bool exclude = true; bool exclude = true;
bool entire_thread_set = false; bool entire_thread_set = false;
bool single_message; bool single_message;
bool decrypt = false; bool decrypt = false;
bool decrypt_set = false;
notmuch_opt_desc_t options[] = { notmuch_opt_desc_t options[] = {
{ .opt_keyword = &format, .name = "format", .keywords = { .opt_keyword = &format, .name = "format", .keywords =
@ -1104,7 +1105,7 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[])
{ .opt_bool = &params.entire_thread, .name = "entire-thread", { .opt_bool = &params.entire_thread, .name = "entire-thread",
.present = &entire_thread_set }, .present = &entire_thread_set },
{ .opt_int = &params.part, .name = "part" }, { .opt_int = &params.part, .name = "part" },
{ .opt_bool = &decrypt, .name = "decrypt" }, { .opt_bool = &decrypt, .name = "decrypt", .present = &decrypt_set },
{ .opt_bool = &params.crypto.verify, .name = "verify" }, { .opt_bool = &params.crypto.verify, .name = "verify" },
{ .opt_bool = &params.output_body, .name = "body" }, { .opt_bool = &params.output_body, .name = "body" },
{ .opt_bool = &params.include_html, .name = "include-html" }, { .opt_bool = &params.include_html, .name = "include-html" },
@ -1118,10 +1119,14 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[])
notmuch_process_shared_options (argv[0]); notmuch_process_shared_options (argv[0]);
if (decrypt) { if (decrypt_set) {
params.crypto.decrypt = NOTMUCH_DECRYPT_TRUE; if (decrypt) {
/* decryption implies verification */ params.crypto.decrypt = NOTMUCH_DECRYPT_TRUE;
params.crypto.verify = true; /* decryption implies verification */
params.crypto.verify = true;
} else {
params.crypto.decrypt = NOTMUCH_DECRYPT_FALSE;
}
} }
/* specifying a part implies single message display */ /* specifying a part implies single message display */

View file

@ -210,6 +210,23 @@ test_expect_equal \
"$output" \ "$output" \
"$expected" "$expected"
test_begin_subtest "notmuch show should show cleartext if session key is present"
output=$(notmuch show id:simple-encrypted@crypto.notmuchmail.org | awk '/^\014part}/{ f=0 }; { if (f) { print $0 } } /^\014part{ ID: 3/{ f=1 }')
expected='This is a top sekrit message.'
if [ $NOTMUCH_HAVE_GMIME_SESSION_KEYS -eq 0 ]; then
test_subtest_known_broken
fi
test_expect_equal \
"$output" \
"$expected"
test_begin_subtest "notmuch show should show nothing if decryption is explicitly disallowed"
output=$(notmuch show --decrypt=false id:simple-encrypted@crypto.notmuchmail.org | 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"
# TODO: test removal of a message from the message store between # TODO: test removal of a message from the message store between
# indexing and reindexing. # indexing and reindexing.