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.
If you're going to store the cleartext index of an encrypted message,
in most situations you might just as well store the session key.
Doing this storage has efficiency and recoverability advantages.
Combined with a schedule of regular OpenPGP subkey rotation and
destruction, this can also offer security benefits, like "deletable
e-mail", which is the store-and-forward analog to "forward secrecy".
But wait, i hear you saying, i have a special need to store cleartext
indexes but it's really bad for me to store session keys! Maybe
(let's imagine) i get lots of e-mails with incriminating photos
attached, and i want to be able to search for them by the text in the
e-mail, but i don't want someone with access to the index to be
actually able to see the photos themselves.
Fret not, the next patch in this series will support your wacky
uncommon use case.
In our consolidation of _notmuch_crypto_decrypt, the callers lost
track a little bit of whether any actual decryption was attempted.
Now that we have the more-subtle "auto" policy, it's possible that
_notmuch_crypto_decrypt could be called without having any actual
decryption take place.
This change lets the callers be a little bit smarter about whether or
not any decryption was actually attempted.
This new automatic decryption policy should make it possible to
decrypt messages that we have stashed session keys for, without
incurring a call to the user's asymmetric keys.
Future patches in this series will introduce new policies; this merely
readies the way for them.
We also convert --try-decrypt to a keyword argument instead of a boolean.
When doing any decryption, if the notmuch database knows of any
session keys associated with the message in question, try them before
defaulting to using default symmetric crypto.
This changeset does the primary work in _notmuch_crypto_decrypt, which
grows some new parameters to handle it.
The primary advantage this patch offers is a significant speedup when
rendering large encrypted threads ("notmuch show") if session keys
happen to be cached.
Additionally, it permits message composition without access to
asymmetric secret keys ("notmuch reply"); and it permits recovering a
cleartext index when reindexing after a "notmuch restore" for those
messages that already have a session key stored.
Note that we may try multiple decryptions here (e.g. if there are
multiple session keys in the database), but we will ignore and throw
away all the GMime errors except for those that come from last
decryption attempt. Since we don't necessarily know at the time of
the decryption that this *is* the last decryption attempt, we'll ask
for the errors each time anyway.
This does nothing if no session keys are stashed in the database,
which is fine. Actually stashing session keys in the database will
come as a subsequent patch.
We will use this centralized function to consolidate the awkward
behavior around different gmime versions.
It's only invoked from two places: mime-node.c's
node_decrypt_and_verify() and lib/index.cc's
_index_encrypted_mime_part().
However, those two places have some markedly distinct logic, so the
interface for this _notmuch_crypto_decrypt function is going to get a
little bit clunky. It's worthwhile, though, for the sake of keeping
these #if directives reasonably well-contained.
In practice, we're going to see this function invoked differently
depending on which gmime we build against. The compatibility layer
forces our code into the lowest-common-denominator -- unable to make
use of new features even when built against a newer version.
Dropping the compatibility layer paves the way for clearer use of
features from GMime 3.0 in future commits.
"typedef GMimeAddressType GMimeRecipientType" is already present
further down in the compatibility wrapper (with other typedefs). We
don't need it twice.
Stripping trailing character is not that uncommon
operation. Particularly, the next patch has to perform it as
well. Lets move it to the separate function to avoid code duplication.
Also the new function has a little improvement: if the character to
strip is repeated several times in the end of a string, function
strips them all.
Signed-off-by: Yuri Volchkov <yuri.volchkov@gmail.com>
The problem shows up on 32 bit architectures where sizeof(time_t) !=
sizeof(gint64). Upcasting the 32 bit time_t to a 64 bit integer
should hopefully be safe.
When compiling as C code (instead of C++) against gmime 3.0, gcc gives
errors like the following:
error: invalid conversion from ‘int’ to ‘GMimeDecryptFlags’ [-fpermissive]
so use explicit *_NONE values instead.
The "key_id" field seems to used for userid in gmime-3.0, while the
keyid is dropped in the fingerprint field if the full fingerprint is
not available.
It turns out that our use of GMimeStreamPipe has only succeeded
because gmime has been ignoring some seek failures; this will no
longer be the case in gmime 3.0, so we use a GMimeStreamPipe, which
does not assume seekability, wrapped in a buffering stream.
Apparently some systems (MacOS?) have a system library called libutil
and the name conflict causes problems. Since this library is quite
notmuch specific, rename it to something less generic.
With the removal of the embedded libsha1, we lost the first and last
user of the platform byte order checks. Remove them from configure,
and remove the endian util header.
Many of the external links found in the notmuch source can be resolved
using https instead of http. This changeset addresses as many as i
could find, without touching the e-mail corpus or expected outputs
found in tests.
Because of limitations in the C type system, we can't a strtok_len
that can work on both const string and non-const strings. The C
library solves this by taking a const char* and returning a char*
in functions like this (e.g., strchr), but that's not const-safe.
Solve it by introducing strtok_len_c, a version of strtok_len for
const strings.
The idea is to provide a more or less drop in replacement for readline
to read from zlib/gzip streams. Take the opportunity to replace
malloc with talloc.
Previously, make_boolean_term did not quote empty boolean terms or
boolean terms that started with '('. These cases are incompatible
with Xapian: empty terms cannot be omitted, and boolean terms that
start with '(' trigger an alternate term quoting syntax.
Fix this by quoting empty terms and terms that contain '('.
Unfortunately old versions of GCC and clang do not provide byte order
macros, so we re-invent them.
If UTIL_BYTE_ORDER is not defined or defined to 0, we fall back to
macros supported by recent versions of GCC and clang
This parses the subset of Xapian's boolean term quoting rules that are
used by make_boolean_term. This is provided as a generic string
utility, but will be used shortly in notmuch restore to parse and
optimize for ID queries.
This is now a generic boolean term quoting function. It performs
minimal quoting to produce user-friendly queries.
This could live in tag-util as well, but it is really nothing specific
to tags (although the conventions are specific to Xapian).
The API is changed from "caller-allocates" to "readline-like". The
scan for max tag length is pushed down into the quoting routine.
Furthermore, this now combines the term prefix with the quoted term;
arguably this is just as easy to do in the caller, but this will
nicely parallel the boolean term parsing function to be introduced
shortly.
This is an amalgamation of code written by David Bremner and myself.
This is to give a home to strtok_len. It's a bit silly to add a header
for one routine, but it needs to be shared between several compilation
units (or at least that's the most natural design).
Annotating functions that do not return with the noreturn attribute
(which is understood by both gcc and clang) prevents static analyzers
from generating false positives (internal_error is used to terminate
the process and is used extensively in error handling code paths).
Remove the return statement that was placed there to appease the
compiler. Functions annotated with noreturn are not supposed to return
any values.
Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>