[PATCH 7/9] add a gpg_path value for notmuch_database_t
Daniel Kahn Gillmor
dkg at fifthhorseman.net
Wed Dec 9 19:39:44 PST 2015
Exposing this to the user of the library lets the user point to
arbitrary gpg executables when trying to decrypt.
---
lib/database-private.h | 3 ++
lib/database.cc | 93 +++++++++++++++++++++++++++++++++++++++++++-------
lib/notmuch.h | 31 +++++++++++++++++
3 files changed, 115 insertions(+), 12 deletions(-)
diff --git a/lib/database-private.h b/lib/database-private.h
index 1bf76c5..9a35044 100644
--- a/lib/database-private.h
+++ b/lib/database-private.h
@@ -171,6 +171,9 @@ struct _notmuch_database {
* notmuch_database_new_revision. */
unsigned long revision;
const char *uuid;
+
+ /* can be NULL, meaning "try to find gpg2 or gpg if possible" */
+ char *gpg_path;
GMimeCryptoContext *gpg_crypto_ctx;
Xapian::QueryParser *query_parser;
diff --git a/lib/database.cc b/lib/database.cc
index d0e8800..c40ce77 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -996,6 +996,7 @@ notmuch_database_open_verbose (const char *path,
notmuch, notmuch->xapian_db->get_uuid ().c_str ());
notmuch->gpg_crypto_ctx = NULL;
+ notmuch->gpg_path = NULL;
notmuch->query_parser = new Xapian::QueryParser;
notmuch->term_gen = new Xapian::TermGenerator;
@@ -1096,6 +1097,10 @@ notmuch_database_close (notmuch_database_t *notmuch)
g_object_unref (notmuch->gpg_crypto_ctx);
notmuch->gpg_crypto_ctx = NULL;
}
+ if (notmuch->gpg_path) {
+ talloc_free(notmuch->gpg_path);
+ notmuch->gpg_path = NULL;
+ }
return status;
}
@@ -2393,17 +2398,6 @@ _notmuch_database_link_message (notmuch_database_t *notmuch,
return status;
}
-static const char*
-_notmuch_database_get_gpg_path (notmuch_database_t *notmuch)
-{
-#define try_gpg_path(z) if (!access(z, X_OK)) return z
- try_gpg_path("/usr/bin/gpg2");
- try_gpg_path("/bin/gpg2");
- try_gpg_path("/usr/bin/gpg");
- try_gpg_path("/bin/gpg");
- return NULL;
-}
-
notmuch_private_status_t
_notmuch_database_get_crypto_for_protocol (notmuch_database_t *notmuch,
const char *protocol,
@@ -2425,7 +2419,7 @@ _notmuch_database_get_crypto_for_protocol (notmuch_database_t *notmuch,
* here? how would this config get into the library? Is
* this an option we can set on the database object? Or
* elsewhere? */
- notmuch->gpg_crypto_ctx = g_mime_gpg_context_new (NULL, _notmuch_database_get_gpg_path(notmuch));
+ notmuch->gpg_crypto_ctx = g_mime_gpg_context_new (NULL, notmuch_database_get_gpg_path(notmuch));
if (! notmuch->gpg_crypto_ctx)
return NOTMUCH_PRIVATE_STATUS_FAILED_CRYPTO_CONTEXT_CREATION;
@@ -2752,3 +2746,78 @@ notmuch_database_status_string (const notmuch_database_t *notmuch)
{
return notmuch->status_string;
}
+
+
+static notmuch_bool_t
+_find_in_path(const char* path)
+{
+ char *c = NULL, *save = NULL, *tok;
+ size_t n;
+ int dfd = -1;
+ notmuch_bool_t ret = FALSE;
+
+ n = confstr(_CS_PATH, NULL, 0);
+ c = (char*)talloc_size(NULL, n);
+ if (!c)
+ return FALSE;
+ confstr(_CS_PATH, c, n);
+
+ tok = strtok_r(c, ":", &save);
+ while (tok) {
+ dfd = open(tok, O_DIRECTORY | O_RDONLY);
+ if (dfd != -1) {
+ if (!faccessat(dfd, path, X_OK, 0)) {
+ ret = TRUE;
+ goto done;
+ }
+ close(dfd);
+ }
+ tok = strtok_r(NULL, ":", &save);
+ }
+done:
+ if (dfd != -1)
+ close(dfd);
+ if (c)
+ talloc_free(c);
+ return ret;
+}
+
+notmuch_status_t
+notmuch_database_set_gpg_path (notmuch_database_t *notmuch, const char* path)
+{
+ /* return success if this matches what is already configured */
+ if ((!path && !notmuch->gpg_path) ||
+ (path && notmuch->gpg_path && 0 == strcmp(path, notmuch->gpg_path)))
+ return NOTMUCH_STATUS_SUCCESS;
+
+ if (!path && !_find_in_path(path))
+ return NOTMUCH_STATUS_FILE_ERROR;
+
+ /* clear any existing gpg_crypto_ctx, since things are changing */
+ if (notmuch->gpg_crypto_ctx) {
+ g_object_unref (notmuch->gpg_crypto_ctx);
+ notmuch->gpg_crypto_ctx = NULL;
+ }
+
+ if (notmuch->gpg_path) {
+ talloc_free(notmuch->gpg_path);
+ notmuch->gpg_path = NULL;
+ }
+
+ if (path)
+ notmuch->gpg_path = talloc_strdup (notmuch, path);
+
+ return NOTMUCH_STATUS_SUCCESS;
+}
+
+const char*
+notmuch_database_get_gpg_path (const notmuch_database_t *notmuch)
+{
+ if (notmuch->gpg_path)
+ return notmuch->gpg_path;
+
+#define try_gpg_path(z) if (_find_in_path(z)) return z
+ try_gpg_path("gpg2");
+ try_gpg_path("gpg");
+ return NULL;
+}
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 809a2ea..e9cfed3 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -591,6 +591,37 @@ notmuch_database_add_message_try_decrypt (notmuch_database_t *database,
notmuch_message_t **message);
/**
+ * Tell the notmuch database where to find GnuPG.
+ *
+ * This is only useful when notmuch might try to use GnuPG to decrypt
+ * MIME parts (see for example
+ * notmuch_database_add_message_try_decrypt). The argument needs to
+ * be an executable version of gpg.
+ *
+ * If this function has never been invoked, notmuch will try to find
+ * gpg in reasonable places.
+ *
+ * This value is not currently stored in the database on disk, it is
+ * only used for this notmuch_database_t while it exists.
+ *
+ * Return value:
+ *
+ * NOTMUCH_STATUS_SUCCESS: the path was accepted and will be used.
+ *
+ * NOTMUCH_STATUS_FILE_ERROR: the path given either wasn't found or
+ * wasn't executable.
+ */
+notmuch_status_t
+notmuch_database_set_gpg_path (notmuch_database_t *database, const char* path);
+
+/**
+ * Find out where the notmuch database will try to find gpg if it
+ * needs to use it.
+ */
+const char*
+notmuch_database_get_gpg_path (const notmuch_database_t *database);
+
+/**
* Remove a message filename from the given notmuch database. If the
* message has no more filenames, remove the message.
*
--
2.6.2
More information about the notmuch
mailing list