mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-24 20:08:10 +01:00
crypto: add --decrypt=nostash to avoid stashing session keys
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.
This commit is contained in:
parent
29648a137c
commit
fccebbaeef
12 changed files with 71 additions and 27 deletions
|
@ -288,7 +288,7 @@ _notmuch_insert()
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
--decrypt)
|
--decrypt)
|
||||||
COMPREPLY=( $( compgen -W "true false auto" -- "${cur}" ) )
|
COMPREPLY=( $( compgen -W "true false auto nostash" -- "${cur}" ) )
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
@ -320,7 +320,7 @@ _notmuch_new()
|
||||||
$split &&
|
$split &&
|
||||||
case "${prev}" in
|
case "${prev}" in
|
||||||
--decrypt)
|
--decrypt)
|
||||||
COMPREPLY=( $( compgen -W "true false auto" -- "${cur}" ) )
|
COMPREPLY=( $( compgen -W "true false auto nostash" -- "${cur}" ) )
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
@ -442,7 +442,7 @@ _notmuch_reindex()
|
||||||
$split &&
|
$split &&
|
||||||
case "${prev}" in
|
case "${prev}" in
|
||||||
--decrypt)
|
--decrypt)
|
||||||
COMPREPLY=( $( compgen -W "true false auto" -- "${cur}" ) )
|
COMPREPLY=( $( compgen -W "true false auto nostash" -- "${cur}" ) )
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -141,6 +141,9 @@ The available configuration items are described below.
|
||||||
**index.decrypt**
|
**index.decrypt**
|
||||||
|
|
||||||
**[STORED IN DATABASE]**
|
**[STORED IN DATABASE]**
|
||||||
|
|
||||||
|
One of ``false``, ``auto``, ``nostash``, or ``true``.
|
||||||
|
|
||||||
When indexing an encrypted e-mail message, if this variable is
|
When indexing an encrypted e-mail message, if this variable is
|
||||||
set to ``true``, notmuch will try to decrypt the message and
|
set to ``true``, notmuch will try to decrypt the message and
|
||||||
index the cleartext, stashing a copy of any discovered session
|
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
|
secret keys. Use ``false`` to avoid decrypting even when a
|
||||||
stashed session key is already present.
|
stashed session key is already present.
|
||||||
|
|
||||||
Be aware that the notmuch index is likely sufficient to
|
``nostash`` is the same as ``true`` except that it will not
|
||||||
reconstruct the cleartext of the message itself, so please
|
stash newly-discovered session keys in the database.
|
||||||
ensure that the notmuch message index is adequately protected.
|
|
||||||
DO NOT USE ``index.decrypt=true`` without considering the
|
Be aware that the notmuch index is likely sufficient (and a
|
||||||
security of your index.
|
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``.
|
Default: ``auto``.
|
||||||
|
|
||||||
|
|
|
@ -51,10 +51,10 @@ Supported options for **insert** include
|
||||||
``--no-hooks``
|
``--no-hooks``
|
||||||
Prevent hooks from being run.
|
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
|
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
|
If ``auto``, and notmuch already knows about a session key for
|
||||||
the message, it will try decrypting using that session key but
|
the message, it will try decrypting using that session key but
|
||||||
will not try to access the user's secret keys. If decryption
|
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
|
message is always stored to disk in its original form
|
||||||
(ciphertext).
|
(ciphertext).
|
||||||
|
|
||||||
Be aware that the index is likely sufficient to reconstruct
|
``nostash`` is the same as ``true`` except that it will not
|
||||||
the cleartext of the message itself, so please ensure that the
|
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
|
notmuch message index is adequately protected. DO NOT USE
|
||||||
``--decrypt=true`` without considering the security of
|
``--decrypt=true`` or ``--decrypt=nostash`` without
|
||||||
your index.
|
considering the security of your index.
|
||||||
|
|
||||||
See also ``index.decrypt`` in **notmuch-config(1)**.
|
See also ``index.decrypt`` in **notmuch-config(1)**.
|
||||||
|
|
||||||
|
|
|
@ -43,10 +43,10 @@ Supported options for **new** include
|
||||||
``--quiet``
|
``--quiet``
|
||||||
Do not print progress or results.
|
Do not print progress or results.
|
||||||
|
|
||||||
``--decrypt=(true|auto|false)``
|
``--decrypt=(true|nostash|auto|false)``
|
||||||
|
|
||||||
If ``true``, when encountering an encrypted message, try to
|
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
|
keys. If ``auto``, try to use any session key already known
|
||||||
to belong to this message, but do not attempt to use the
|
to belong to this message, but do not attempt to use the
|
||||||
user's secret keys. If decryption is successful, index 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
|
key is certainly sufficient) to reconstruct the cleartext of
|
||||||
the message itself, so please ensure that the notmuch message
|
the message itself, so please ensure that the notmuch message
|
||||||
index is adequately protected. DO NOT USE ``--decrypt=true``
|
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)**.
|
See also ``index.decrypt`` in **notmuch-config(1)**.
|
||||||
|
|
||||||
|
|
|
@ -21,23 +21,27 @@ messages using the supplied options.
|
||||||
|
|
||||||
Supported options for **reindex** include
|
Supported options for **reindex** include
|
||||||
|
|
||||||
``--decrypt=(true|auto|false)``
|
``--decrypt=(true|nostash|auto|false)``
|
||||||
|
|
||||||
If ``true``, when encountering an encrypted message, try to
|
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
|
discovered. If ``auto``, and notmuch already knows about a
|
||||||
session key for the message, it will try decrypting using that
|
session key for the message, it will try decrypting using that
|
||||||
session key but will not try to access the user's secret keys.
|
session key but will not try to access the user's secret keys.
|
||||||
If decryption is successful, index the cleartext itself.
|
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
|
If ``false``, notmuch reindex will also delete any stashed
|
||||||
session keys for all messages matching the search terms.
|
session keys for all messages matching the search terms.
|
||||||
|
|
||||||
Be aware that the index is likely sufficient to reconstruct
|
Be aware that the index is likely sufficient (and a stashed
|
||||||
the cleartext of the message itself, so please ensure that the
|
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
|
notmuch message index is adequately protected. DO NOT USE
|
||||||
``--decrypt=true`` without considering the security of your
|
``--decrypt=true`` or ``--decrypt=nostash`` without
|
||||||
index.
|
considering the security of your index.
|
||||||
|
|
||||||
See also ``index.decrypt`` in **notmuch-config(1)**.
|
See also ``index.decrypt`` in **notmuch-config(1)**.
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@ notmuch_database_get_default_indexopts (notmuch_database_t *db)
|
||||||
(!(strcasecmp(decrypt_policy, "no"))) ||
|
(!(strcasecmp(decrypt_policy, "no"))) ||
|
||||||
(!(strcasecmp(decrypt_policy, "0"))))
|
(!(strcasecmp(decrypt_policy, "0"))))
|
||||||
notmuch_indexopts_set_decrypt_policy (ret, NOTMUCH_DECRYPT_FALSE);
|
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);
|
free (decrypt_policy);
|
||||||
|
|
|
@ -2242,6 +2242,7 @@ typedef enum {
|
||||||
NOTMUCH_DECRYPT_FALSE,
|
NOTMUCH_DECRYPT_FALSE,
|
||||||
NOTMUCH_DECRYPT_TRUE,
|
NOTMUCH_DECRYPT_TRUE,
|
||||||
NOTMUCH_DECRYPT_AUTO,
|
NOTMUCH_DECRYPT_AUTO,
|
||||||
|
NOTMUCH_DECRYPT_NOSTASH,
|
||||||
} notmuch_decryption_policy_t;
|
} notmuch_decryption_policy_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -730,7 +730,7 @@ notmuch_reply_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
|
|
||||||
notmuch_process_shared_options (argv[0]);
|
notmuch_process_shared_options (argv[0]);
|
||||||
if (decrypt_set)
|
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 ();
|
notmuch_exit_if_unsupported_format ();
|
||||||
|
|
||||||
|
|
|
@ -1121,7 +1121,8 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
|
|
||||||
if (decrypt_set) {
|
if (decrypt_set) {
|
||||||
if (decrypt) {
|
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 */
|
/* decryption implies verification */
|
||||||
params.crypto.verify = true;
|
params.crypto.verify = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -104,6 +104,7 @@ const notmuch_opt_desc_t notmuch_shared_indexing_options [] = {
|
||||||
(notmuch_keyword_t []){ { "false", NOTMUCH_DECRYPT_FALSE },
|
(notmuch_keyword_t []){ { "false", NOTMUCH_DECRYPT_FALSE },
|
||||||
{ "true", NOTMUCH_DECRYPT_TRUE },
|
{ "true", NOTMUCH_DECRYPT_TRUE },
|
||||||
{ "auto", NOTMUCH_DECRYPT_AUTO },
|
{ "auto", NOTMUCH_DECRYPT_AUTO },
|
||||||
|
{ "nostash", NOTMUCH_DECRYPT_NOSTASH },
|
||||||
{ 0, 0 } },
|
{ 0, 0 } },
|
||||||
.name = "decrypt" },
|
.name = "decrypt" },
|
||||||
{ }
|
{ }
|
||||||
|
|
|
@ -188,6 +188,29 @@ test_expect_equal \
|
||||||
"$output" \
|
"$output" \
|
||||||
"$expected"
|
"$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
|
add_email_corpus crypto
|
||||||
|
|
||||||
test_begin_subtest "indexing message fails when secret key not available"
|
test_begin_subtest "indexing message fails when secret key not available"
|
||||||
|
|
|
@ -199,7 +199,7 @@ _notmuch_crypto_decrypt (bool *attempted,
|
||||||
#if (GMIME_MAJOR_VERSION < 3)
|
#if (GMIME_MAJOR_VERSION < 3)
|
||||||
#if HAVE_GMIME_SESSION_KEYS
|
#if HAVE_GMIME_SESSION_KEYS
|
||||||
gboolean oldgetsk = g_mime_crypto_context_get_retrieve_session_key (crypto_ctx);
|
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)
|
if (newgetsk != oldgetsk)
|
||||||
/* This could return an error, but we can't do anything about it, so ignore it */
|
/* 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);
|
g_mime_crypto_context_set_retrieve_session_key (crypto_ctx, newgetsk, NULL);
|
||||||
|
@ -212,7 +212,7 @@ _notmuch_crypto_decrypt (bool *attempted,
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
GMimeDecryptFlags flags = GMIME_DECRYPT_NONE;
|
GMimeDecryptFlags flags = GMIME_DECRYPT_NONE;
|
||||||
if (decrypt_result)
|
if (decrypt == NOTMUCH_DECRYPT_TRUE && decrypt_result)
|
||||||
flags |= GMIME_DECRYPT_EXPORT_SESSION_KEY;
|
flags |= GMIME_DECRYPT_EXPORT_SESSION_KEY;
|
||||||
ret = g_mime_multipart_encrypted_decrypt(part, flags, NULL,
|
ret = g_mime_multipart_encrypted_decrypt(part, flags, NULL,
|
||||||
decrypt_result, err);
|
decrypt_result, err);
|
||||||
|
|
Loading…
Reference in a new issue